Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x 将HSV遮罩拆分为多个矩形_Python 3.x_Opencv_Image Processing - Fatal编程技术网

Python 3.x 将HSV遮罩拆分为多个矩形

Python 3.x 将HSV遮罩拆分为多个矩形,python-3.x,opencv,image-processing,Python 3.x,Opencv,Image Processing,我从图像中创建了一个HSV遮罩。结果如下: 我的目标是绘制适合遮罩高度或宽度的多重矩形,如下所示: 我遇到了2道题 我不知道如何在创建矩形的掩码中定位起点和终点。若我使用for循环逐行扫描遮罩,它可能会将遮罩分成两部分。 有时,在一张图像中还包含两个不同的遮罩。如何绘制矩形? 任何人都可以给我一些建议吗?您可以使用cv2.findContour()搜索您的最大轮廓(十字形状)。它返回轮廓的坐标数组。然后,您可以搜索具有最高X坐标(即最右点)、最低X坐标(最左点)、最高Y坐标(即最底点)和

我从图像中创建了一个HSV遮罩。结果如下:

我的目标是绘制适合遮罩高度或宽度的多重矩形,如下所示:

我遇到了2道题

  • 我不知道如何在创建矩形的掩码中定位起点和终点。若我使用for循环逐行扫描遮罩,它可能会将遮罩分成两部分。

  • 有时,在一张图像中还包含两个不同的遮罩。如何绘制矩形?


  • 任何人都可以给我一些建议吗?

    您可以使用
    cv2.findContour()
    搜索您的最大轮廓(十字形状)。它返回轮廓的坐标数组。然后,您可以搜索具有最高X坐标(即最右点)、最低X坐标(最左点)、最高Y坐标(即最底点)和最低Y坐标(即最高点)的轮廓点。在获得所有4个值后,可以再次搜索轮廓中具有该值的所有点,并将它们附加到4个不同的列表中,稍后对它们进行排序,以便将这些点作为淹没在底图上:

    从这一点开始,我将列表转换为numpy数组,因为这对我来说更容易。你可以用任何其他方法

    然后,问题就在于你想要多少个矩形,以及你想如何显示它们。在我的示例代码中,您必须输入需要多少相同大小的矩形,最后一个是剩余矩形的大小。我首先在Y坐标(绿色)上显示矩形,然后在X坐标上显示矩形,X坐标分为两段(左侧和右侧),因为它们的距离略有不同,我不想在Y坐标矩形上绘制,因为它们没有在示例图像上绘制。您可以根据需要更改写入矩形的逻辑。希望它能对你有所帮助,或者给你一个如何处理的想法。干杯

    示例代码:

    import cv2
    import numpy as np
    
    # Read image and search for contours. 
    img = cv2.imread('cross.png')
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    _, threshold = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY)
    _, contours, hierarchy = cv2.findContours(threshold,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
    
    # Select the biggest contour (if you wish to segmentize only the cross-like contour). 
    cnt = max(contours, key=cv2.contourArea)
    
    # Create empty lists for appending key points. 
    top_vertical = []
    bottom_vertical = []
    left_horizontal = []
    right_horizontal = []
    
    # Setting the starter values for N, S, E, W. 
    top = 10000
    bottom = 0
    left = 10000
    right = 0
    
    # Loop to get highest key values of N, S, E, W.  
    for i in cnt:
        y = int(i[:,1])
        x = int(i[:, 0])
        if x < left:
            left = int(x)
        if x > right:
            right = int(x)
        if y < top:
            top = int(y)
        if y > bottom:
            bottom = int(y)
    
    # Loop for appending all points containing key values of N, S, E, W.   
    for i in cnt:
        if int(i[:,1]) == top:
            up = (int(i[:,0]), int(i[:,1]))
            top_vertical.append(up)
        if int(i[:,1]) == bottom:
            down = (int(i[:,0]), int(i[:,1]))
            bottom_vertical.append(down)
        if int(i[:,0]) == left:
            l = (int(i[:,0]), int(i[:,1]))
            left_horizontal.append(l)
        if int(i[:,0]) == right:
            r = (int(i[:,0]), int(i[:,1]))
            right_horizontal.append(r)
    
    
    # Sorting the lists. 
    top_vertical.sort(key=lambda tup: tup[0])
    bottom_vertical.sort(key=lambda tup: tup[0])
    left_horizontal.sort(key=lambda tup: tup[1])
    right_horizontal.sort(key=lambda tup: tup[1])
    
    # Optional drawing of key points. 
    '''cv2.circle(img,(top_vertical[0]), 4, (0,0,255), -1)
    cv2.circle(img,(top_vertical[-1]), 4, (0,0,255), -1)
    cv2.circle(img,(bottom_vertical[0]), 4, (0,0,255), -1)
    cv2.circle(img,(bottom_vertical[-1]), 4, (0,0,255), -1)
    cv2.circle(img,(left_horizontal[0]), 4, (0,0,255), -1)
    cv2.circle(img,(left_horizontal[-1]), 4, (0,0,255), -1)
    cv2.circle(img,(right_horizontal[0]), 4, (0,0,255), -1)
    cv2.circle(img,(right_horizontal[-1]), 4, (0,0,255), -1)'''
    
    # Transforming lists to arrays. 
    top_vertical = np.array(top_vertical)
    bottom_vertical = np.array(bottom_vertical)
    left_horizontal = np.array(left_horizontal)
    right_horizontal = np.array(right_horizontal)
    
    # Calculating height and weight of the contour.
    distance_y = bottom - top
    distance_x = right - left
    
    # Inputs for the number of same size segments. 
    a = input('Input the number of same size segments in Y coordinate: ')
    b = input('Input the number of same size segments in left X coordinate: ')
    c = input('Input the number of same size segments in right X coordinate: ')
    
    # Calculation of area per segment and limit for the lenght of combined segments (height and weight) . 
    segment_y = distance_y/int(a)
    segment_x_reference = int(top_vertical[0,0]) - int(left_horizontal[0,0])
    segment_x = segment_x_reference/int(b)
    segment_x_right_reference = int(right_horizontal[0,0]) - int(top_vertical[-1,0])
    segment_x_right = segment_x_right_reference/int(c)
    
    # Drawing rectangles on the Y axis.
    for i in range(1,20):
        sq = int(segment_y)*i
        if sq < distance_y:
            cv2.rectangle(img,(top_vertical[0,0], top_vertical[0,1]),((top_vertical[-1,0]),top_vertical[0,1] + sq),(0,255,0),1)
        else:
            sq = distance_y
            cv2.rectangle(img,(top_vertical[0,0], top_vertical[0,1]),((top_vertical[-1,0]),sq),(0,255,0),1)
            break
    
    # Drawing rectangles on the left side of X axis.   
    for i in range(1,20):
        sq = int(segment_x)*i
        if sq < segment_x_reference:
            cv2.rectangle(img,(left_horizontal[0,0], left_horizontal[0,1]),((left_horizontal[0,0])+sq, left_horizontal[-1,1]),(255,0,0),1)
        else:
            sq = segment_x_reference
            cv2.rectangle(img,(left_horizontal[0,0], left_horizontal[0,1]),((left_horizontal[0,0])+sq, left_horizontal[-1,1]),(255,0,0),1)
            break
    
    # Drawing rectangles on the right side of X axis. 
    for i in range(1,20):
        sq = int(segment_x_right)*i
        if sq < segment_x_right_reference:
            cv2.rectangle(img,(right_horizontal[0,0], right_horizontal[0,1]),((right_horizontal[0,0])-sq, right_horizontal[-1,1]),(255,0,0),1)
        else:
            sq = segment_x_right_reference
            cv2.rectangle(img,(right_horizontal[0,0], right_horizontal[0,1]),((right_horizontal[0,0])-sq, right_horizontal[-1,1]),(255,0,0),1)
            break
    
    # Displaying result. 
    cv2.imshow('img', img)
    

    您的矩形是否有特定的尺寸需要考虑,或者每个遮罩中是否有最佳数量的矩形需要绘制?激发灵感的帖子+1。这种方法也适用于不规则形状的轮廓吗?谢谢!我认为这是行不通的,因为它假设外墙是直线,并且它有一个十字架形状。如果你改变了极值点的阈值,如果它有多个交叉点(如t形)或没有交叉点(如普通正方形)等,它可能适用于不规则形状。但这可能需要大量工作:)很好的解决方案。但是,如果交叉形状围绕图像中的某个噪声点,则可能会影响4个值(上、右、左、下)的提取。你有什么办法解决这个问题吗?嗯……如果只有一两个像素,你可以将“if int(i[:,1])==top”改为“if int(i[:,1])>=top-2”等等,或者你可以制作附加列表来附加top、left、right、bottom的值,并选择具有最高值且在列表中出现一次或两次以上的值。
    import cv2
    import numpy as np
    
    # Read image and search for contours. 
    img = cv2.imread('cross.png')
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    _, threshold = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY)
    _, contours, hierarchy = cv2.findContours(threshold,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
    
    # Select the biggest contour (if you wish to segmentize only the cross-like contour). 
    cnt = max(contours, key=cv2.contourArea)
    
    # Create empty lists for appending key points. 
    top_vertical = []
    bottom_vertical = []
    left_horizontal = []
    right_horizontal = []
    
    # Setting the starter values for N, S, E, W. 
    top = 10000
    bottom = 0
    left = 10000
    right = 0
    
    # Loop to get highest key values of N, S, E, W.  
    for i in cnt:
        y = int(i[:,1])
        x = int(i[:, 0])
        if x < left:
            left = int(x)
        if x > right:
            right = int(x)
        if y < top:
            top = int(y)
        if y > bottom:
            bottom = int(y)
    
    # Loop for appending all points containing key values of N, S, E, W.   
    for i in cnt:
        if int(i[:,1]) == top:
            up = (int(i[:,0]), int(i[:,1]))
            top_vertical.append(up)
        if int(i[:,1]) == bottom:
            down = (int(i[:,0]), int(i[:,1]))
            bottom_vertical.append(down)
        if int(i[:,0]) == left:
            l = (int(i[:,0]), int(i[:,1]))
            left_horizontal.append(l)
        if int(i[:,0]) == right:
            r = (int(i[:,0]), int(i[:,1]))
            right_horizontal.append(r)
    
    
    # Sorting the lists. 
    top_vertical.sort(key=lambda tup: tup[0])
    bottom_vertical.sort(key=lambda tup: tup[0])
    left_horizontal.sort(key=lambda tup: tup[1])
    right_horizontal.sort(key=lambda tup: tup[1])
    
    # Optional drawing of key points. 
    '''cv2.circle(img,(top_vertical[0]), 4, (0,0,255), -1)
    cv2.circle(img,(top_vertical[-1]), 4, (0,0,255), -1)
    cv2.circle(img,(bottom_vertical[0]), 4, (0,0,255), -1)
    cv2.circle(img,(bottom_vertical[-1]), 4, (0,0,255), -1)
    cv2.circle(img,(left_horizontal[0]), 4, (0,0,255), -1)
    cv2.circle(img,(left_horizontal[-1]), 4, (0,0,255), -1)
    cv2.circle(img,(right_horizontal[0]), 4, (0,0,255), -1)
    cv2.circle(img,(right_horizontal[-1]), 4, (0,0,255), -1)'''
    
    # Transforming lists to arrays. 
    top_vertical = np.array(top_vertical)
    bottom_vertical = np.array(bottom_vertical)
    left_horizontal = np.array(left_horizontal)
    right_horizontal = np.array(right_horizontal)
    
    # Calculating height and weight of the contour.
    distance_y = bottom - top
    distance_x = right - left
    
    # Inputs for the number of same size segments. 
    a = input('Input the number of same size segments in Y coordinate: ')
    b = input('Input the number of same size segments in left X coordinate: ')
    c = input('Input the number of same size segments in right X coordinate: ')
    
    # Calculation of area per segment and limit for the lenght of combined segments (height and weight) . 
    segment_y = distance_y/int(a)
    segment_x_reference = int(top_vertical[0,0]) - int(left_horizontal[0,0])
    segment_x = segment_x_reference/int(b)
    segment_x_right_reference = int(right_horizontal[0,0]) - int(top_vertical[-1,0])
    segment_x_right = segment_x_right_reference/int(c)
    
    # Drawing rectangles on the Y axis.
    for i in range(1,20):
        sq = int(segment_y)*i
        if sq < distance_y:
            cv2.rectangle(img,(top_vertical[0,0], top_vertical[0,1]),((top_vertical[-1,0]),top_vertical[0,1] + sq),(0,255,0),1)
        else:
            sq = distance_y
            cv2.rectangle(img,(top_vertical[0,0], top_vertical[0,1]),((top_vertical[-1,0]),sq),(0,255,0),1)
            break
    
    # Drawing rectangles on the left side of X axis.   
    for i in range(1,20):
        sq = int(segment_x)*i
        if sq < segment_x_reference:
            cv2.rectangle(img,(left_horizontal[0,0], left_horizontal[0,1]),((left_horizontal[0,0])+sq, left_horizontal[-1,1]),(255,0,0),1)
        else:
            sq = segment_x_reference
            cv2.rectangle(img,(left_horizontal[0,0], left_horizontal[0,1]),((left_horizontal[0,0])+sq, left_horizontal[-1,1]),(255,0,0),1)
            break
    
    # Drawing rectangles on the right side of X axis. 
    for i in range(1,20):
        sq = int(segment_x_right)*i
        if sq < segment_x_right_reference:
            cv2.rectangle(img,(right_horizontal[0,0], right_horizontal[0,1]),((right_horizontal[0,0])-sq, right_horizontal[-1,1]),(255,0,0),1)
        else:
            sq = segment_x_right_reference
            cv2.rectangle(img,(right_horizontal[0,0], right_horizontal[0,1]),((right_horizontal[0,0])-sq, right_horizontal[-1,1]),(255,0,0),1)
            break
    
    # Displaying result. 
    cv2.imshow('img', img)
    
    Input the number of same size segments in Y coordinate: 5
    Input the number of same size segments in left X coordinate: 2
    Input the number of same size segments in right X coordinate: 2