Example #1
0
def layout_analysis():
    path = 'test.jpg'

    img_ = cv2.imread(path, 0)

    _, img_bit = cv2.threshold(img_, 127, 255, cv2.THRESH_BINARY)

    boxes = getAllMiniBoundingBoxesOfImage(img_bit)
    print('all boxes len: ', len(boxes))

    cv2.imshow("original", img_bit)

    cv2.waitKey(0)
    cv2.destroyAllWindows()
Example #2
0
def merge_radical_left_right(img):
    if img is None:
        print("img is none!")
        return

    rects = getAllMiniBoundingBoxesOfImage(img)

    rect_imgs = getConnectedComponentsOfGrayScale(img)
    print("rect img num: ", len(rect_imgs))
    print(rects)

    left_side_list = []
    right_side_list = []
    for i in range(len(rects)):
        x, y, w, h = rects[i]

        cent_x = x + int(w / 2)
        cent_y = y + int(h / 2)

        if cent_x > 127:
            right_side_list.append(rects[i])
        else:
            left_side_list.append(rects[i])

        print(cent_x, cent_y)

    print(left_side_list)
    print(right_side_list)

    # check images
    bk_left = createBlankGrayscaleImageWithSize(img.shape)
    bk_right = createBlankGrayscaleImageWithSize(img.shape)

    for rimg in rect_imgs:
        rect = getSingleMaxBoundingBoxOfImage(rimg)
        if rect in left_side_list:
            bk_left = merge_two_images(bk_left, rimg)
        elif rect in right_side_list:
            bk_right = merge_two_images(bk_right, rimg)

    return (bk_left, bk_right)
Example #3
0
import cv2
import numpy

from utils.Functions import getCenterOfGravity, getSingleMaxBoundingBoxOfImage, \
    getAllMiniBoundingBoxesOfImage, getSkeletonOfImage, getContourOfImage, getContourImage, removeExtraBranchesOfSkeleton

path = "test_images/yong.png"

img = cv2.imread(path)

img_bit = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
_, img_bit = cv2.threshold(img_bit, 100, 255, cv2.THRESH_BINARY)

# remove littine noise
boxes = getAllMiniBoundingBoxesOfImage(img_bit)
for box in boxes:
    if box[2] < 50 or box[3] < 50:
        img_bit[box[1]:box[1] + box[3], box[0]:box[0] + box[2]] = 255

# size and aspect ratio
img_rbg = cv2.cvtColor(img_bit, cv2.COLOR_GRAY2RGB)
img_layout = img_rbg.copy()

x, y, w, h = getSingleMaxBoundingBoxOfImage(img_bit)
img_rbg = cv2.rectangle(img_rbg, (x, y), (x + w, y + h), (0, 255, 0), 2)
img_cog = img_rbg.copy()

cv2.line(img_rbg, (x, y), (x + w, y + h), (0, 0, 255), 2)

# cog
cog_x, cog_y = getCenterOfGravity(img_bit)
Example #4
0
    def segmentationBtn(self):
        """
        Characters segmentation.
        :return:
        """
        print("Segmentation button clicked!")

        self.scene.clear()
        self.image_characters = []
        self.characters_name = []

        img_rgb = self.image_rgb.copy()

        # distance threshold
        dist_threshold = int(self.thre_dist_ledit.text())
        width_threshold = int(self.thre_width_ledit.text())

        img_binary = self.image_binary.copy()

        boxes = getAllMiniBoundingBoxesOfImage(img_binary)
        # filter boxes with threshold of width
        boxes = filterBoxWithWidth(boxes, width_threshold)
        print("original boxes len: %d" % len(boxes))

        # remove inside rectangles
        boxes_noinside = removeContainedBoxes(boxes)

        # cluster rectangles based on the distance threshold
        lines = []
        for i in range(len(boxes_noinside)):
            rect_item = [i]

            ct_rect_i = getCenterOfRectangles(boxes_noinside[i])
            start_index = i
            end_index = start_index

            for j in range(len(boxes_noinside)):
                if i == j:
                    continue
                ct_rect_j = getCenterOfRectangles(boxes_noinside[j])

                dist = math.sqrt((ct_rect_j[0] - ct_rect_i[0])**2 +
                                 (ct_rect_j[1] - ct_rect_i[1])**2)
                if dist <= dist_threshold:
                    rect_item.append(j)

                    end_index = j
                    lines.append([start_index, end_index])
            if end_index == start_index:
                lines.append([start_index, end_index])

        # cluster based on the lines
        rects = []
        for i in range(len(lines)):
            line = lines[i]
            if line[0] == line[1]:
                rects.append([line[0]])
            else:
                new_set = set(line)
                for j in range(len(lines)):
                    if i == j:
                        continue
                    set_j = set(lines[j])
                    if len(new_set.intersection(set_j)) != 0:
                        new_set = new_set.union(set_j)
                if list(new_set) not in rects:
                    rects.append(list(new_set))

        # remove the repeat items
        rects_ = []
        repet_id = []
        for i in range(len(rects)):
            if i in repet_id:
                continue
            repet_id.append(i)
            len1 = len(repet_id)
            for j in range(len(rects)):
                if i == j:
                    continue
                if len(set(rects[j]).intersection(set(rects[i]))) != 0:
                    new_set = list(set(rects[j]).union(set(rects[i])))
                    rects_.append(new_set)
                    repet_id.append(j)
            if len1 == len(repet_id):
                rects_.append(rects[i])

        del rects
        rects = rects_.copy()
        del rects_

        for i in range(len(rects)):
            new_rect = combineRectangles(boxes_noinside, rects[i])
            # add border of rectangle with 5 pixels
            new_r_x = 0 if new_rect[0] - 5 < 0 else new_rect[0] - 5
            new_r_y = 0 if new_rect[1] - 5 < 0 else new_rect[1] - 5
            new_r_w = img_binary.shape[1] - new_rect[
                0] if new_rect[0] + new_rect[2] + 10 > img_binary.shape[
                    1] else new_rect[2] + 10
            new_r_h = img_binary.shape[0] - new_rect[
                0] if new_rect[1] + new_rect[3] + 10 > img_binary.shape[
                    0] else new_rect[3] + 10

            cv2.rectangle(img_rgb, (new_r_x, new_r_y),
                          (new_r_x + new_r_w, new_r_y + new_r_h), (255, 0, 0),
                          1)
            self.image_characters.append((new_r_x, new_r_y, new_r_w, new_r_h))
            self.characters_name.append("character_" + str(i + 1))

        # display RGB image
        img_rgb = np.array(img_rgb)
        qimg = QImage(img_rgb.data, img_rgb.shape[1], img_rgb.shape[0],
                      QImage.Format_RGB888)
        self.image_pix = QPixmap.fromImage(qimg)
        self.temp_image_pix = self.image_pix.copy()

        self.scene.addPixmap(self.image_pix)
        self.scene.setSceneRect(QRectF())
        self.image_gview.fitInView(self.scene.sceneRect(), Qt.KeepAspectRatio)
        self.scene.update()

        self.char_slm.setStringList(self.characters_name)

        self.statusbar.showMessage("Segmentation processing successed!")
        del qimg, img_binary, img_rgb, boxes_noinside, boxes
Example #5
0
def autoSmoothContoursOfComponent(component, blockSize=3, ksize=3, k=0.04):
    """

    :param component:
    :return:
    """
    if component is None:
        return
    # 5. Using corner detection to get corner regions
    corner_component = np.float32(component)
    dst = cv2.cornerHarris(corner_component,
                           blockSize=blockSize,
                           ksize=ksize,
                           k=k)
    dst = cv2.dilate(dst, None)

    corners_area_points = []
    for y in range(dst.shape[0]):
        for x in range(dst.shape[1]):
            if dst[y][x] > 0.1 * dst.max():
                corners_area_points.append((x, y))
    print("corner area points num: %d" % len(corners_area_points))

    # 6. Determine center points of corner areas
    blank_gray = createBlankGrayscaleImage(component)
    for pt in corners_area_points:
        blank_gray[pt[1]][pt[0]] = 0.0

    rectangles = getAllMiniBoundingBoxesOfImage(blank_gray)

    corners_area_center_points = []
    for rect in rectangles:
        corners_area_center_points.append(
            (rect[0] + int(rect[2] / 2.), rect[1] + int(rect[3] / 2.)))
    print("corner area center points num: %d" %
          len(corners_area_center_points))

    # based the distance to end points and cross points, remove extra corners area center points

    component_skeleton = getSkeletonOfImage(component)
    end_points = getEndPointsOfSkeletonLine(component_skeleton)
    cross_points = getCrossPointsOfSkeletonLine(component_skeleton)

    # remove extra branches
    # img_skeleton = removeBranchOfSkeletonLine(img_skeleton, end_points, cross_points)
    # end_points = getEndPointsOfSkeletonLine(img_skeleton)
    # cross_points = getEndPointsOfSkeletonLine(img_skeleton)

    # detect valid corner region center points closed to end points and cross points
    valid_corners_area_center_points = []
    dist_threshold = 40
    for pt in corners_area_center_points:
        is_valid = False
        for ept in end_points:
            dist = math.sqrt((pt[0] - ept[0])**2 + (pt[1] + ept[1])**2)
            if dist <= dist_threshold:
                is_valid = True
                break
        if is_valid:
            valid_corners_area_center_points.append(pt)
            continue
        for cpt in cross_points:
            dist = math.sqrt((pt[0] - cpt[0])**2 + (pt[1] - cpt[1])**2)
            if dist <= dist_threshold:
                is_valid = True
                break
        if is_valid:
            valid_corners_area_center_points.append(pt)

    print("valid corner area center points num: %d" %
          len(valid_corners_area_center_points))

    del blank_gray

    # 7. Get all contours of component
    component_contours = getContourOfImage(component)
    contours = getConnectedComponents(component_contours, connectivity=8)
    print("contours num: %d" % len(contours))

    # 8. Process contours to get closed and 1-pixel width contours
    contours_processed = []
    for cont in contours:
        cont = removeBreakPointsOfContour(cont)
        contours_processed.append(cont)
    print("contours processed num: %d" % len(contours_processed))

    # 9. Find corner points of conthours closed to corner region center points. For each contour, there is a coner points list.
    contours_corner_points = []
    for i in range(len(contours_processed)):
        corner_points = []
        contour = contours_processed[i]

        for pt in valid_corners_area_center_points:
            x0 = target_x = pt[0]
            y0 = target_y = pt[1]
            min_dist = 10000
            # search target point in region: 20 * 20 of center is (x0, y0)
            for y in range(y0 - 10, y0 + 10):
                for x in range(x0 - 10, x0 + 10):
                    if contour[y][x] == 255:
                        continue
                    dist = math.sqrt((x - x0)**2 + (y - y0)**2)
                    if dist < min_dist:
                        min_dist = dist
                        target_x = x
                        target_y = y
            if min_dist < 5:
                corner_points.append((target_x, target_y))

        contours_corner_points.append(corner_points)
    total_num = 0
    for cont in contours_corner_points:
        total_num += len(cont)
    if total_num == len(valid_corners_area_center_points):
        print("corner points not ignored")
    else:
        print("corner points be ignored")

    # 10. Separate contours into sub-contours based on the corner points on different contours
    sub_contours = []
    for i in range(len(contours_processed)):
        contour = contours_processed[i]
        corner_points = contours_corner_points[i]
        # sorted the contour
        contour_points_sorted = sortPointsOnContourOfImage(contour)
        # sorted the corner points
        corner_points_sorted = []
        for pt in contour_points_sorted:
            if pt in corner_points:
                corner_points_sorted.append(pt)
        # sepate the contour into sub-contour
        for j in range(len(corner_points_sorted)):
            start_pt = corner_points_sorted[j]
            end_pt = None
            if j == len(corner_points_sorted) - 1:
                end_pt = corner_points_sorted[0]
            else:
                end_pt = corner_points_sorted[j + 1]
            # find indexes of start point and end point in contour_points_sorted
            start_index = contour_points_sorted.index(start_pt)
            end_index = contour_points_sorted.index(end_pt)

            # separate
            sub_contour = None
            if start_index <= end_index:
                if end_index == len(contour_points_sorted) - 1:
                    sub_contour = contour_points_sorted[
                        start_index:len(contour_points_sorted)]
                    sub_contour.append(contour_points_sorted[0])
                else:
                    sub_contour = contour_points_sorted[start_index:end_index +
                                                        1]
            else:
                sub_contour = contour_points_sorted[
                    start_index:len(contour_points_sorted
                                    )] + contour_points_sorted[0:end_index + 1]

            sub_contours.append(sub_contour)
    print("sub contours num: %d" % len(sub_contours))

    # 11. Beizer curve fit all sub-contours under maximal error
    max_error = 100
    sub_contours_smoothed = []

    for id in range(len(sub_contours)):
        # single sub-contour
        sub_contour = np.array(sub_contours[id])

        if len(sub_contour) < 2:
            continue
        beziers = fitCurve(sub_contour, maxError=max_error)
        sub_contour_smoothed = []

        for bez in beziers:
            bezier_points = draw_cubic_bezier(bez[0], bez[1], bez[2], bez[3])
            sub_contour_smoothed += bezier_points

        sub_contours_smoothed.append(sub_contour_smoothed)

    # 12. Merge sub-contours together
    img_smoothed_gray = createBlankGrayscaleImage(component)

    # merge all smoothed sub-contours
    for sub in sub_contours_smoothed:
        for pt in sub:
            img_smoothed_gray[pt[1]][pt[0]] = 0.0
    # process smoothed contours to get closed and 1-pixel width
    img_smoothed_gray = getSkeletonOfImage(img_smoothed_gray)

    # remove single points that 8

    cv2.imshow("img_smoothed_gray", img_smoothed_gray)

    contours_smoothed = getConnectedComponents(img_smoothed_gray)

    if len(contours_smoothed) == 1:
        # no hole exist, directly fill black in the contour
        cont = contours_smoothed[0]
        cont_points = sortPointsOnContourOfImage(cont)
        cont_points = np.array([cont_points], "int32")

        fill_contour_smooth = np.ones_like(component) * 255
        fill_contour_smooth = np.array(fill_contour_smooth, dtype=np.uint8)
        fill_contour_smooth = cv2.fillPoly(fill_contour_smooth, cont_points, 0)

        return fill_contour_smooth
    else:
        # exist hole, should processed
        print("there are holes!")
        fill_img_list = []
        hole_points = []
        for cont in contours_smoothed:
            cont_points = sortPointsOnContourOfImage(cont)
            cont_points = np.array([cont_points], "int32")

            fill_contour_smooth = np.ones_like(component) * 255
            fill_contour_smooth = np.array(fill_contour_smooth, dtype=np.uint8)
            fill_contour_smooth = cv2.fillPoly(fill_contour_smooth,
                                               cont_points, 0)

            valid_num = same_num = 0
            for y in range(component.shape[0]):
                for x in range(component.shape[1]):
                    if component[y][x] == 0.0:
                        valid_num += 1
                        if fill_contour_smooth[y][x] == 0.0:
                            same_num += 1

            if 1.0 * same_num / valid_num > 0.8:
                fill_img_list.append(fill_contour_smooth)
                print("ratio: %f" % (1.0 * same_num / valid_num))
            else:
                print("ratio: %f" % (1.0 * same_num / valid_num))
                for y in range(fill_contour_smooth.shape[0]):
                    for x in range(fill_contour_smooth.shape[1]):
                        if fill_contour_smooth[y][x] == 0.0:
                            hole_points.append((x, y))

        # merge filled images
        blank_temp = np.ones_like(component) * 255
        for fl in fill_img_list:
            for y in range(fl.shape[0]):
                for x in range(fl.shape[1]):
                    if fl[y][x] == 0.0:
                        blank_temp[y][x] = fl[y][x]
        # hole points
        for pt in hole_points:
            blank_temp[pt[1]][pt[0]] = 255

        return blank_temp
Example #6
0
def main():
    src_path = '../calligraphys/hurulin1.jpg'

    img = cv2.imread(src_path, 0)

    img_rgb = cv2.imread(src_path)

    img = cv2.resize(img, (0, 0), fx=SCALE_RATIO, fy=SCALE_RATIO)
    if len(img_rgb.shape) == 2:
        img_rgb = cv2.cvtColor(img_rgb, cv2.COLOR_GRAY2RGB)

    img_rgb = cv2.resize(img_rgb, (0, 0), fx=SCALE_RATIO, fy=SCALE_RATIO)

    img_rgb_noinside = copy.deepcopy(img_rgb)
    img_rgb_nointersected = copy.deepcopy(img_rgb)

    # image processing

    # image binary
    _, img_bit = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
    print(img_bit.shape)

    # inverting color
    # img_bit = 255 - img_bit

    # get all bounding boxes
    boxes = getAllMiniBoundingBoxesOfImage(img_bit)
    print("boxes len:%d" % len(boxes))

    # filter the boxes, and remove the biggest and too small boxes
    boxes_filtered = []
    for box in boxes:
        if box[2] < WIDTH_THRESHOLD * SCALE_RATIO or box[3] < HEIGHT_THRESHOLD * SCALE_RATIO:
            continue

        if box[2] >= img_bit.shape[0] or box[3] >= img_bit.shape[1]:
            continue

        boxes_filtered.append(box)
    print("after filtered boxes len: %d" % len(boxes_filtered))

    # removed contained rectangles
    inside_id = []
    for i in range(len(boxes_filtered)):
        ri_x = boxes_filtered[i][0]
        ri_y = boxes_filtered[i][1]
        ri_w = boxes_filtered[i][2]
        ri_h = boxes_filtered[i][3]

        for j in range(len(boxes_filtered)):
            if i == j or j in inside_id:
                continue
            rj_x = boxes_filtered[j][0]
            rj_y = boxes_filtered[j][1]
            rj_w = boxes_filtered[j][2]
            rj_h = boxes_filtered[j][3]

            # rect_j  inside rect_i
            if ri_x <= rj_x and ri_y <= rj_y and ri_x + ri_w >= rj_x + rj_w and ri_y + ri_h >= rj_y + rj_h:
                if j not in inside_id:
                    inside_id.append(j)
            elif rj_x <= ri_x and rj_y <= ri_y and rj_x + rj_w >= ri_x + ri_w and rj_y + rj_h >= ri_y + ri_h:
                if i not in inside_id:
                    inside_id.append(i)
    print("insie id len: %d " % len(inside_id))

    boxes_noinside = []
    for i in range(len(boxes_filtered)):
        if i in inside_id:
            continue
        boxes_noinside.append(boxes_filtered[i])
    print("no inside box len: %d" % len(boxes_noinside))

    # add rectangles to original images

    for box in boxes_noinside:
        img_rgb_noinside = cv2.rectangle(img_rgb_noinside, (box[0], box[1]), (box[0] + box[2], box[1] + box[3]), (255, 0, 0), 1)

    # merge the intersected rectangles
    intersected_id_list = []
    for i in range(len(boxes_noinside)):
        intersected_item = []
        rect_i = boxes_noinside[i]
        intersected_item.append(i)
        for j in range(len(boxes_noinside)):
            if i == j:
                continue
            rect_j = boxes_noinside[j]
            if isIntersectedOfTwoRectangles(rect_i, rect_j):
                intersected_item.append(j)
        intersected_id_list.append(intersected_item)
    print("Before merge the id list")
    print(intersected_id_list)

    # merge the id list
    intersected_id_list_merged = []
    used_id = []
    for i in range(len(intersected_id_list)):
        if i in used_id:
            continue
        # no intersected with others
        # if len(intersected_id_list[i]) == 1:
        #     intersected_id_list_merged.append(intersected_id_list[i])
        #     continue

        new_id = intersected_id_list[i]
        # intersected with others
        for j in range(i+1, len(intersected_id_list)):
            if len(set(intersected_id_list[i]).intersection(set(intersected_id_list[j]))) == 0:
                continue
            # intersected
            new_id = list(set(new_id).union(set(intersected_id_list[j])))
            used_id.append(j)
        intersected_id_list_merged.append(new_id)

    print("After merge")
    print(intersected_id_list_merged)

    boxes_nointersected = []

    for item in intersected_id_list_merged:
        rt_x, rt_y, rt_w, rt_h = combineRectangles(boxes_noinside, item)
        boxes_nointersected.append([rt_x, rt_y, rt_w, rt_h])

    print(len(boxes_nointersected))

    for box in boxes_nointersected:
        img_rgb_nointersected = cv2.rectangle(img_rgb_nointersected, (box[0], box[1]), (box[0] + box[2], box[1] + box[3]), (0, 0, 255), 1)

    cv2.imshow("noinside", img_rgb_noinside)
    cv2.imshow("nointersected", img_rgb_nointersected)

    cv2.waitKey(0)
    cv2.destroyAllWindows()
Example #7
0
dst = cv2.cornerHarris(corner_component, blockSize=3, ksize=3, k=0.04)
dst = cv2.dilate(dst, None)

corners_area_points = []
for y in range(dst.shape[0]):
    for x in range(dst.shape[1]):
        if dst[y][x] > 0.1 * dst.max():
            corners_area_points.append((x, y))
print("corner area points num: %d" % len(corners_area_points))

# 6. Determine center points of corner areas
blank_gray = createBlankGrayscaleImage(component)
for pt in corners_area_points:
    blank_gray[pt[1]][pt[0]] = 0.0

rectangles = getAllMiniBoundingBoxesOfImage(blank_gray)

corners_area_center_points = []
for rect in rectangles:
    corners_area_center_points.append(
        (rect[0] + int(rect[2] / 2.), rect[1] + int(rect[3] / 2.)))
print("corner area center points num: %d" % len(corners_area_center_points))

end_points = getEndPointsOfSkeletonLine(skeleton)
cross_points = getCrossPointsOfSkeletonLine(skeleton)

valid_corners_area_center_points = []
dist_threshold = 40
for pt in corners_area_center_points:
    is_valid = False
    for ept in end_points:
Example #8
0
def autoStrokeExtractFromComponent(component):
    """
    Automatically strokes extract from the component.
    :param component:
    :return:
    """
    strokes = []
    if component is None:
        return strokes

    # 6. Get skeletons of component.
    comp_skeleton = getSkeletonOfImage(component.copy())
    # cv2.imshow("skeleton_original", comp_skeleton)

    # 7. Process the skeleton by remove extra branches.
    comp_skeleton = removeShortBranchesOfSkeleton(comp_skeleton,
                                                  length_threshold=30)
    # cv2.imshow("skeleton_smoothed", comp_skeleton)

    # 8. Get the end points and cross points after skeleton processed
    end_points = getEndPointsOfSkeletonLine(comp_skeleton)
    cross_points = getCrossPointsOfSkeletonLine(comp_skeleton)
    print("end points num: %d ,and cross points num: %d" %
          (len(end_points), len(cross_points)))

    # 9. Get contour image of component
    comp_contours_img = getContourImage(component.copy())

    # 10. Detect the number of contours and return all contours
    comp_contours = getConnectedComponents(comp_contours_img, connectivity=8)
    print("contours num: %d" % len(comp_contours))

    # 11. Detect the corner regions of component
    #       Harris corner detector
    corner_region_img = np.float32(component.copy())
    dst = cv2.cornerHarris(corner_region_img, blockSize=3, ksize=3, k=0.04)
    dst = cv2.dilate(dst, None)

    # get all points in corners area
    corners_area_points = []
    for y in range(dst.shape[0]):
        for x in range(dst.shape[1]):
            if dst[y][x] > 0.1 * dst.max():
                corners_area_points.append((x, y))

    # get all center points of corner area
    corners_img = createBlankGrayscaleImage(component)
    for pt in corners_area_points:
        corners_img[pt[1]][pt[0]] = 0.0

    rectangles = getAllMiniBoundingBoxesOfImage(corners_img)

    corners_area_center_points = []
    for rect in rectangles:
        corners_area_center_points.append(
            (rect[0] + int(rect[2] / 2.), rect[1] + int(rect[3] / 2.)))

    # get all corner points in coutour image.
    corners_points = []
    for pt in corners_area_center_points:
        if comp_contours_img[pt[1]][pt[0]] == 0.0:
            corners_points.append(pt)
        else:
            min_dist = 100000
            min_x = min_y = 0
            for y in range(comp_contours_img.shape[0]):
                for x in range(comp_contours_img.shape[1]):
                    cpt = comp_contours_img[y][x]
                    if cpt == 0.0:
                        dist = math.sqrt((x - pt[0])**2 + (y - pt[1])**2)
                        if dist < min_dist:
                            min_dist = dist
                            min_x = x
                            min_y = y
            # points on contour
            corners_points.append((min_x, min_y))
    print("corners points num: %d" % len(corners_points))

    # 12. Get valid corner points based on the end points and cross points
    corners_points = getValidCornersPoints(corners_points,
                                           cross_points,
                                           end_points,
                                           distance_threshold=30)
    print("corners points num: %d" % len(corners_points))

    if len(corners_points) == 0:
        print("no corner points")
        strokes.append(component)
        return strokes

    # 13. Cluster these corner points based on the distance between them and cross points
    corners_points_cluster = getClusterOfCornerPoints(corners_points,
                                                      cross_points)
    print("corner points cluster num: %d" % len(corners_points_cluster))

    # 14. Generate cropping lines between two corner points
    crop_lines = getCropLines(corners_points_cluster, None)
    print("cropping lines num: %d" % len(crop_lines))

    # 15. Separate the components based on the cropping lines
    component_ = component.copy()

    # add white and 1-pixel width line in component to separate it.
    for line in crop_lines:
        cv2.line(component_, line[0], line[1], 255, 1)

    # 16. Get parts of component.
    comp_parts = []
    # invert color !!!
    component_ = 255 - component_
    ret, labels = cv2.connectedComponents(component_, connectivity=4)
    print(ret)
    for r in range(1, ret):
        img_ = createBlankGrayscaleImage(component_)
        for y in range(component_.shape[0]):
            for x in range(component_.shape[1]):
                if labels[y][x] == r:
                    img_[y][x] = 0.0
        if img_[0][0] != 0.0 and isValidComponent(img_, component):
            comp_parts.append(img_)
    print("parts of component num: %d" % len(comp_parts))

    # 17. Add cropping lines to corresponding parts of component
    # add lines to parts of component.
    for i in range(len(comp_parts)):
        part = comp_parts[i]

        for line in crop_lines:
            start_dist = getDistanceBetweenPointAndComponent(line[0], part)
            end_dist = getDistanceBetweenPointAndComponent(line[1], part)

            if start_dist <= 3 and end_dist <= 3:
                cv2.line(part, line[0], line[1], 0, 1)

    # 18. Find intersection parts of component
    used_index = []
    intersect_parts_index = []
    for i in range(len(comp_parts)):
        part = comp_parts[i]
        num = 0  # number of lines in part
        for line in crop_lines:
            if part[line[0][1]][line[0][0]] == 0.0 and part[line[1][1]][
                    line[1][0]] == 0.0:
                num += 1
        if num == 4:  # 4 lines in one part, this part is the intersection part
            intersect_parts_index.append(i)
            used_index.append(i)
    print("intersection parts num: %d" % len(intersect_parts_index))

    # 19. Find the relation part and crop lines - one line -> one part or three part (part1 + intersect_part + part2)
    intersect_parts_crop_lines_index = []
    for i in range(len(crop_lines)):
        line = crop_lines[i]
        for index in intersect_parts_index:
            intersect_part = comp_parts[index]
            if intersect_part[line[0][1]][
                    line[0][0]] == 0.0 and intersect_part[line[1][1]][
                        line[1][0]] == 0.0:
                # this line in intersection part
                intersect_parts_crop_lines_index.append(i)
    print("crop lines in intersection part num: %d" %
          len(intersect_parts_crop_lines_index))

    # Cropping lines are divided into two types: in intersect part and not in this part.
    line_parts_relation = []
    for index in intersect_parts_crop_lines_index:
        line = crop_lines[index]

        # line and parts that are connected by this crop line: A - intersect_part - B
        line_connected_parts = []
        # find intersection part contains this line
        for i in intersect_parts_index:
            intersect_part = comp_parts[i]
            if intersect_part[line[0][1]][
                    line[0][0]] == 0.0 and intersect_part[line[1][1]][
                        line[1][0]] == 0.0:
                # line in this intersect part
                line_connected_parts.append(i)
        # find two parts connectd by this crop line
        for i in range(len(comp_parts)):

            # part should not be the intersect part
            if i in intersect_parts_index:
                continue

            # check only end point of line in part.
            part = comp_parts[i]
            if part[line[0][1]][line[0][0]] == 0.0 and part[line[1][1]][line[1][0]] != 0.0 or \
                    part[line[0][1]][line[0][0]] != 0.0 and part[line[1][1]][line[1][0]] == 0.0:
                line_connected_parts.append(i)

        # add line connected parts to relation list.
        if line_connected_parts not in line_parts_relation:
            line_parts_relation.append(line_connected_parts)

    # add independent parts to relation of line and parts
    for i in range(len(comp_parts)):
        line_connected_parts = []
        is_independent = True
        for relation in line_parts_relation:
            if i in relation:
                is_independent = False
        # check this part is independent or not
        if is_independent:
            line_connected_parts.append(i)

        if line_connected_parts != []:
            line_parts_relation.append(line_connected_parts)

    # 20. Merge parts based on the line parts relation
    for i in range(len(line_parts_relation)):
        # blank image
        blank_ = createBlankGrayscaleImage(component)
        # parts relation list
        relation = line_parts_relation[i]

        for rel in relation:
            part = comp_parts[rel]
            if part is None:
                continue
            # merge part and blank image
            for y in range(part.shape[0]):
                for x in range(part.shape[1]):
                    if part[y][x] == 0.0:
                        blank_[y][x] = 0.0

        # add to strokes list
        strokes.append(blank_)
    return strokes
Example #9
0
def main():
    scale_ratio = 0.4
    # src_path = '../calligraphys/yaomengqi1.jpg'
    # src_path = '../calligraphys/ouyangxun1.jpg'
    src_path = '../calligraphys/hurulin1.jpg'

    img = cv2.imread(src_path, 0)

    img_rgb = cv2.imread(src_path)

    img = cv2.resize(img, (0, 0), fx=scale_ratio, fy=scale_ratio)
    if len(img_rgb.shape) == 2:
        img_rgb = cv2.cvtColor(img_rgb, cv2.COLOR_GRAY2RGB)

    img_rgb = cv2.resize(img_rgb, (0,0), fx=scale_ratio, fy=scale_ratio)

    # image processing

    # image binary
    _, img_bit = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
    print(img_bit.shape)

    # inverting color
    # img_bit = 255 - img_bit

    # get all bounding boxes
    boxes = getAllMiniBoundingBoxesOfImage(img_bit)
    print(len(boxes))

    boxes_ = []

    for box in boxes:
        if box[2] < 30*scale_ratio or box[3] < 30*scale_ratio:
            continue

        if box[2] >= img_bit.shape[0] or box[3] >= img_bit.shape[1]:
            continue

        boxes_.append(box)

    print(len(boxes_))

    # remove inside rectangles
    inside_id = []
    for i in range(len(boxes_)):
        ri_x = boxes_[i][0]
        ri_y = boxes_[i][1]
        ri_w = boxes_[i][2]
        ri_h = boxes_[i][3]

        for j in range(len(boxes_)):
            if i == j or j in inside_id:
                continue
            rj_x = boxes_[j][0]
            rj_y = boxes_[j][1]
            rj_w = boxes_[j][2]
            rj_h = boxes_[j][3]

            # rect_j  inside rect_i
            if ri_x <= rj_x and ri_y <= rj_y and ri_x+ri_w >= rj_x+rj_w and ri_y+ri_h >= rj_y+rj_h:
                if j not in inside_id:
                    inside_id.append(j)
            elif rj_x <= ri_x and rj_y <= ri_y and rj_x+rj_w >= ri_x+ri_w and rj_y+rj_h >= ri_y+ri_h:
                if i not in inside_id:
                    inside_id.append(i)

    print("inside id len: %d" % len(inside_id))

    boxes_noinsde = []
    for i in range(len(boxes_)):
        if i in inside_id:
            continue
        boxes_noinsde.append(boxes_[i])
    print("no inside box len: %d" % len(boxes_noinsde))

    # add rectangles to original images
    for box in boxes_noinsde:
        img_rgb = cv2.rectangle(img_rgb, (box[0], box[1]), (box[0] + box[2], box[1] + box[3]), (255, 0, 0), 1)

    # handle the intersect rectangles

    # add line of center of rectangles
    dist_threshod = 70 * scale_ratio
    for i in range(len(boxes_noinsde)):
        ct_rect_i = getCenterOfRectangles(boxes_noinsde[i])

        for j in range(len(boxes_noinsde)):
            if i == j:
                continue
            ct_rect_j = getCenterOfRectangles(boxes_noinsde[j])

            dist = math.sqrt((ct_rect_j[0] - ct_rect_i[0]) * (ct_rect_j[0] - ct_rect_i[0]) + (ct_rect_j[1] - ct_rect_i[1]) * (ct_rect_j[1] - ct_rect_i[1]))

            if dist > dist_threshod:
                continue
            img_rgb = cv2.line(img_rgb, (ct_rect_i[0], ct_rect_i[1]), (ct_rect_j[0], ct_rect_j[1]), (0, 255, 0), 1)

    # cluster rectangles based on the distance
    rect_clustor = []
    for i in range(len(boxes_noinsde)):
        rect_item = []
        rect_item.append(i)

        ct_rect_i = getCenterOfRectangles(boxes_noinsde[i])

        for j in range(len(boxes_noinsde)):
            ct_rect_j = getCenterOfRectangles(boxes_noinsde[j])

            dist = math.sqrt( (ct_rect_j[0] - ct_rect_i[0]) * (ct_rect_j[0] - ct_rect_i[0]) + (ct_rect_j[1] - ct_rect_i[1]) * (
                            ct_rect_j[1] - ct_rect_i[1]))
            if dist <= dist_threshod and j not in rect_item:
                rect_item.append(j)
        rect_clustor.append(rect_item)

    print(rect_clustor)

    # merge the clustor
    final_clustor = []
    used_index = []
    for i in range(len(rect_clustor)):
        if i in used_index:
            continue
        new_clustor = rect_clustor[i]
        # merge
        for j in range(i+1, len(rect_clustor)):
            if len(set(new_clustor).intersection(set(rect_clustor[j]))) == 0:
                continue
            new_clustor = list(set(new_clustor).union(set(rect_clustor[j])))
            used_index.append(j)
        final_clustor.append(new_clustor)

    print(final_clustor)

    for i in range(len(final_clustor)):

        new_rect = combineRectangles(boxes_noinsde, final_clustor[i])
        img_rgb = cv2.rectangle(img_rgb, (new_rect[0], new_rect[1]), (new_rect[0] + new_rect[2], new_rect[1] + new_rect[3]), (0, 0, 255), 1)






    # the projecting histogram on X-axis (columns)
    # x_sum = np.zeros(img_bit.shape[1])
    # for j in range(img_bit.shape[0]):
    #     x_sum += 255 - img_bit[j, :]
    # x_sum = x_sum / 255
    # print(x_sum)
    #
    # plt.subplot(121)
    # plt.imshow(img_bit, cmap='gray')
    # plt.subplot(122)
    # plt.plot(x_sum)
    # plt.show()



    cv2.imshow("source", img_rgb)

    cv2.waitKey(0)
    cv2.destroyAllWindows()