【问题标题】:Get all rectangles from a shape on Opencv4从Opencv4上的形状中获取所有矩形
【发布时间】:2019-12-09 23:54:39
【问题描述】:

我正在使用 opencv 4,我想从一个形状中获取所有矩形的可能性,因为我正在从形状中寻找框或矩形,但是当我将框连接在它们之间时,我找不到多少我在图片中的盒子。

我使用 cv2.cornerHarris() 搜索拐角并尝试从拐角获取矩形,但我没有使用此函数找到拐角的准确性。

有谁知道获得我期望的结果的最佳方法是什么?或者opencv的哪些功能最适合从这种形状的形状中找到矩形??

我有这张图片:

这是我期望的结果(4 个矩形):

编辑:

通过 Shubham Jaiswal 的回答,我得到了预期的结果,但对于下一张图像,我没有很好的结果,但是通过他的代码,我得到了一个尝试获取图像矩形的起点。

效果不佳的图片:

提前致谢。

最好的问候。

【问题讨论】:

    标签: opencv contour


    【解决方案1】:
    import cv2
    import numpy as np
    from collections import defaultdict
    
    #read the input image
    inp_image = cv2.imread("9EtWF.jpg")
    #convert the image to gray scale
    gray_image = cv2.cvtColor(inp_image.copy(),cv2.COLOR_BGR2GRAY)
    
    #do a morphological closing and edge detection
    kernel = np.ones((5,5),np.uint8)
    closing = cv2.morphologyEx(gray_image, cv2.MORPH_CLOSE, kernel)
    edge_detection = cv2.Canny(closing,50,255)
    
    #get the outline of the region of interest
    indices = np.where(edge_detection != [0])
    coordinates = [[i, j] for i,j in zip(indices[1], indices[0])]
    
    def validate_merge(l1,l2,thresh_x,thresh_y):
        return (abs(l2[1] - l1[1])<= thresh_y and abs(l2[0]-l1[0])<= thresh_x)
    
    #loop over all the points and merge them based on their x and y coordinates
    final_horizontal_list = []
    temp_list = []
    temp_list.append(coordinates[0])
    for idx in range(1,len(coordinates)-2):
        if validate_merge(coordinates[idx],coordinates[idx+1],10,10): 
            temp_list.append(coordinates[idx])            
        else:
            temp_list.append(coordinates[idx])
            if len(temp_list) > 10:
                merge_segment_flag = False
                for segment_idx,segment in enumerate(final_horizontal_list):
                    if validate_merge(temp_list[-1],segment[0],10,10) or validate_merge(segment[-1],temp_list[0],10,10):
                        final_horizontal_list[segment_idx]+=temp_list
                        final_horizontal_list[segment_idx].sort()
                        merge_segment_flag = True
                        break
                if not merge_segment_flag:
                    final_horizontal_list.append(temp_list)
            temp_list = []
    
    block_idxs = [idx for idx in range(len(final_horizontal_list))]
    
    def validate_y_groupings(l0,l1):
    
        diff1 = l0[0][0] - l1[0][0]
        diff2 = l0[-1][0]-l1[-1][0]
        final_coords_list = []
        diff1_y = l0[0][1] - l1[0][1]
        diff2_y = l0[-1][1]-l1[-1][1]
        if abs(diff1) <= 50 and abs(diff2)<=50:
            if diff1 < 0:
                if diff1_y < 0:
                    final_coords_list.append(l0[0])
                else:
                    final_coords_list.append([l0[0][0],l1[0][1]])
    
            else:
                if diff1_y < 0:
                    final_coords_list.append([l1[0][0],l0[0][1]])
                else:
                    final_coords_list.append(l1[0])
    
            if diff2 < 0:
                if diff2_y < 0:
                    final_coords_list.append(l1[-1])
                else:
                    final_coords_list.append([l1[-1][0],l0[-1][1]])
            else:
                if diff2_y < 0:
                    final_coords_list.append([l0[-1][0],l1[-1][1]])
                else:
                    final_coords_list.append(l0[-1])
    
    
            return True,final_coords_list
        else:
            return False,None
    
    #get the boundaries for the right and left rectangles and store the top_left and bottom_right co-ordinates in a variable
    pair_group_list = []
    pair_grouped_list = []
    final_rectangle_list = []
    for seg_index in block_idxs:
        search_list = list(set(block_idxs).difference([seg_index]).difference(pair_grouped_list))
        for search_idx in search_list:
            validation_result = validate_y_groupings(final_horizontal_list[seg_index],final_horizontal_list[search_idx])
            if validation_result[0]:
                pair_group_list.append([seg_index,search_idx])
                final_rectangle_list.append(validation_result[1])
                pair_grouped_list+=[seg_index,search_idx]
                break
    
    
    updated_search_list = list(set(block_idxs).difference(pair_grouped_list))
    coords_dict = defaultdict(lambda:[])
    for idx in updated_search_list:
        coords_dict[idx]+=final_horizontal_list[idx][0]
    
    sorted_coords_list = sorted(coords_dict.items(),key = lambda kv:(kv[1][1]))
    #get the boundaries for the topmost rectangle
    triplet_group_1 = sorted_coords_list[0:len(sorted_coords_list)-1]
    sorted_triplet_group_1 = sorted(triplet_group_1,key = lambda x:x[1][0])
    
    final_rectangle_list.append([sorted_triplet_group_1[1][1],sorted_triplet_group_1[2][1]])
    
    #get the boundaries for the middle rectangle
    triplet_group_2 = []
    triplet_group_2+=[sorted_triplet_group_1[0],sorted_coords_list[-1],sorted_triplet_group_1[-1]]
    #find the top_left coordinates 
    diff1 = triplet_group_2[0][1][0] - triplet_group_2[1][1][0]
    temp_rect_list = []
    #get the correct x and y co-ordinates for the top_left
    if diff1 < 0:
        temp_rect_list.append(triplet_group_2[0][1])
    else:
        temp_rect_list.append([triplet_group_2[1][1][0],triplet_group_2[0][1][1]])
    
    #get the correct bottom right points
    l0 = final_horizontal_list[triplet_group_2[1][0]][-1]
    l1 = final_horizontal_list[triplet_group_2[2][0]][-1]
    diff2 = l0[0] - l1[0] 
    
    if diff2 < 0:
        temp_rect_list.append([l1[0],l0[1]])
    else:
        temp_rect_list.append(l0)
    
    final_rectangle_list.append(temp_rect_list)
    
    #draw and save the image
    
    copy_image = inp_image.copy()
    for coords in final_rectangle_list:
        cv2.rectangle(copy_image,tuple(coords[0]),tuple(coords[-1]),(0,255,0),3)
    #     cv2.line(copy_image, tuple(coords[0]), tuple(coords[-1]), (0, 255, 0), thickness=3, lineType=8)
        print(coords[0],coords[-1])
        cv2.imshow('img', copy_image)
        cv2.waitKey(0)
    cv2.destroyAllWindows()
    cv2.imwrite("output.jpg",copy_image)
    del copy_image
    

    上述代码的输出图像:

    虽然边界并不完美,但只要稍加调整,就能轻松搞定。注意:我使用了 opencv 3.4.2 作为这个结果,但同样适用于 opencv 4。

    【讨论】:

    • 感谢您的回复,第一张图片可以正常工作,但如果矩形成角度,则算法不会检测到矩形。我编辑了这个问题。我正在编辑您的代码以获取所有情况下的功能。
    猜你喜欢
    • 1970-01-01
    • 2014-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多