Use connected-component labeling for finding letters.
This commit is contained in:
parent
74570e6760
commit
b05cc3853e
3 changed files with 52 additions and 22 deletions
|
|
@ -60,12 +60,13 @@ class PageScene(QGraphicsScene):
|
||||||
self.pageItem.setGraphicsEffect(shadow)
|
self.pageItem.setGraphicsEffect(shadow)
|
||||||
|
|
||||||
letterPen = QPen(QColor(50, 50, 50, 100))
|
letterPen = QPen(QColor(50, 50, 50, 100))
|
||||||
letterBrush = QBrush(QColor(255, 255, 0, 60))
|
letterBrush = QBrush(QColor(255, 255, 0, 80))
|
||||||
linePen = QPen(QColor(255, 150, 150, 100))
|
linePen = QPen(QColor(255, 150, 150, 100))
|
||||||
for line in page:
|
for line in page:
|
||||||
for letter in line:
|
for word in line:
|
||||||
if not letter.image.isspace:
|
for letter in word:
|
||||||
self.addRect(letter.x1, letter.y1, letter.width, letter.height, letterPen, letterBrush)
|
if not letter.image.isspace:
|
||||||
|
self.addRect(letter.x1, letter.y1, letter.width, letter.height, letterPen, letterBrush)
|
||||||
self.addRect(line.x1, line.y1, line.width, line.height, Qt.red)
|
self.addRect(line.x1, line.y1, line.width, line.height, Qt.red)
|
||||||
|
|
||||||
def addPage(self, page):
|
def addPage(self, page):
|
||||||
|
|
|
||||||
|
|
@ -151,22 +151,36 @@ class Image(object):
|
||||||
bottom_margin = _get_margin_height(reversed(self.bitmap))
|
bottom_margin = _get_margin_height(reversed(self.bitmap))
|
||||||
return self[top_margin:self.height - bottom_margin, :]
|
return self[top_margin:self.height - bottom_margin, :]
|
||||||
|
|
||||||
def _iter_lines(self, min_space, T=False):
|
def _iter_lines(self, min_space):
|
||||||
line_start = None
|
def iter_lines():
|
||||||
prev_line_end = 0
|
line_start = None
|
||||||
|
prev_line_end = 0
|
||||||
|
|
||||||
for i, row in enumerate(self.bitmap):
|
for i, row in enumerate(self.bitmap):
|
||||||
if _is_nonblank(row):
|
if _is_nonblank(row):
|
||||||
if line_start is None:
|
if line_start is None:
|
||||||
line_start = i
|
line_start = i
|
||||||
height = line_start - prev_line_end
|
else:
|
||||||
if height >= min_space:
|
if line_start is not None:
|
||||||
yield self[prev_line_end:line_start]
|
yield self[line_start:i,:]
|
||||||
else:
|
line_start = None
|
||||||
if line_start is not None:
|
prev_line_end = i
|
||||||
yield self[line_start:i,:]
|
|
||||||
line_start = None
|
def merge_lines(lines):
|
||||||
prev_line_end = i
|
prev_line = None
|
||||||
|
for line in lines:
|
||||||
|
if prev_line is None:
|
||||||
|
prev_line = line
|
||||||
|
else:
|
||||||
|
if line.y1 - prev_line.y2 < min_space:
|
||||||
|
prev_line = self[prev_line.y1:line.y2]
|
||||||
|
else:
|
||||||
|
yield prev_line
|
||||||
|
prev_line = line
|
||||||
|
if prev_line is not None:
|
||||||
|
yield prev_line
|
||||||
|
|
||||||
|
return merge_lines(iter_lines())
|
||||||
|
|
||||||
|
|
||||||
class SubImage(Image):
|
class SubImage(Image):
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,14 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
from scipy import ndimage
|
||||||
|
|
||||||
from .image import Image
|
from .image import Image
|
||||||
|
|
||||||
|
|
||||||
|
CONNECTIVITY8 = ndimage.generate_binary_structure(2, 2)
|
||||||
|
|
||||||
|
|
||||||
class PageObject(object):
|
class PageObject(object):
|
||||||
def __init__(self, image):
|
def __init__(self, image):
|
||||||
self.image = image
|
self.image = image
|
||||||
|
|
@ -55,14 +60,24 @@ class PageObject(object):
|
||||||
|
|
||||||
class Page(PageObject):
|
class Page(PageObject):
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
for line_img in self.image._iter_lines(min_space=200):
|
for line_img in self.image._iter_lines(min_space=5):
|
||||||
yield Line(line_img)
|
yield Line(line_img)
|
||||||
|
|
||||||
|
|
||||||
class Line(PageObject):
|
class Line(PageObject):
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
for rotated_letter_img in self.image.T._iter_lines(min_space=10, T=True):
|
for rotated_word_img in self.image.T._iter_lines(min_space=10):
|
||||||
yield Letter(rotated_letter_img.T.strip())
|
yield Word(rotated_word_img.T)
|
||||||
|
|
||||||
|
|
||||||
|
class Word(PageObject):
|
||||||
|
def __iter__(self):
|
||||||
|
labels, max_label = ndimage.label(self.image.bitmap, CONNECTIVITY8)
|
||||||
|
obj_indices = ndimage.find_objects(labels, max_label)
|
||||||
|
letter_images = (self.image[obj_index] for obj_index in obj_indices)
|
||||||
|
letters = (Letter(image) for image in letter_images)
|
||||||
|
sorted_letters = sorted(letters, key=lambda letter: (letter.x1, -letter.y1))
|
||||||
|
return iter(sorted_letters)
|
||||||
|
|
||||||
|
|
||||||
class Letter(PageObject):
|
class Letter(PageObject):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue