Python 如何获取和存储楼层平面图像中房间的质心坐标?

Python 如何获取和存储楼层平面图像中房间的质心坐标?,python,image,opencv,image-processing,computer-vision,Python,Image,Opencv,Image Processing,Computer Vision,我有一个由多个房间组成的平面图。使用Python,我希望找到每个房间的中心,并以(x,y)的形式存储坐标,以便进一步使用它们进行数学计算。现有的drawContours和FindContours函数有助于确定等高线,但如何将获得的值存储到列表中 该图像表示具有多个房间的示例楼层平面 我尝试使用矩,但该函数无法正常工作。 这是我的密码: k= [] # Going through every contours found in the image. for cnt in contours :

我有一个由多个房间组成的平面图。使用Python,我希望找到每个房间的中心,并以(x,y)的形式存储坐标,以便进一步使用它们进行数学计算。现有的
drawContours
FindContours
函数有助于确定等高线,但如何将获得的值存储到列表中

该图像表示具有多个房间的示例楼层平面

我尝试使用
,但该函数无法正常工作。

这是我的密码:

k= []
# Going through every contours found in the image. 
for cnt in contours : 

    approx = cv2.approxPolyDP(cnt, 0.009 * cv2.arcLength(cnt, True), True) 

    # draws boundary of contours. 
    cv2.drawContours(img, [approx], -1, (0, 0,255), 3)  

    # Used to flatted the array containing 
    # the co-ordinates of the vertices. 
    n = approx.ravel()  
    i = 0
    x=[]
    y=[]

    for j in n : 
        if(i % 2 == 0): 
            x = n[i] 
            y = n[i + 1]



            # String containing the co-ordinates. 
            string = str(x) + " ," + str(y)  


            if(i == 0): 
                # text on topmost co-ordinate. 
                cv2.putText(img, string, (x, y), 
                                font, 0.5, (255, 0, 0))
                k.append(str((x, y))) 


            else: 
                # text on remaining co-ordinates. 
                cv2.putText(img, string, (x, y),  
                          font, 0.5, (0, 255, 0))  
                k.append(str((x, y)))

        i = i + 1


# Showing the final image. 
cv2_imshow( img )  
# Exiting the window if 'q' is pressed on the keyboard. 
if cv2.waitKey(0) & 0xFF == ord('q'):  
    cv2.destroyAllWindows()

这里有一个简单的方法:

  • 获取二值图像。加载图像、灰度和

  • 删除文本。然后我们使用过滤来删除小于某个阈值的轮廓。我们通过使用填充来有效地删除这些轮廓

  • 找到矩形框并获得质心坐标。我们再次找到轮廓,然后使用轮廓区域和进行过滤。然后,我们找到每个轮廓的矩,这些矩为我们提供了


  • 下面是一个可视化:

    删除文本

    结果

    坐标

    [(93, 241), (621, 202), (368, 202), (571, 80), (317, 79), (93, 118)]
    
    代码

    导入cv2
    将numpy作为np导入
    #加载图像、灰度、大津阈值
    image=cv2.imread('1.png')
    灰色=cv2.CVT颜色(图像,cv2.COLOR\u BGR2GRAY)
    thresh=cv2.阈值(灰色,0,255,cv2.thresh\u二进制\u INV+cv2.thresh\u OTSU)[1]
    #删除文本
    cnts=cv2.查找对象(阈值、cv2.RETR\u树、cv2.链近似值、简单值)
    如果len(cnts)==2个其他cnts[1],则cnts=cnts[0]
    对于碳纳米管中的碳:
    面积=cv2。轮廓面积(c)
    如果面积小于1000:
    cv2.拉深轮廓(阈值[c],-1,0,-1)
    thresh=255-thresh
    结果=cv2.CVT颜色(阈值,cv2.COLOR_GRAY2BGR)
    坐标=[]
    #找到矩形框并获得质心坐标
    cnts=cv2.查找对象(阈值、cv2.RETR\u树、cv2.链近似值、简单值)
    如果len(cnts)==2个其他cnts[1],则cnts=cnts[0]
    对于碳纳米管中的碳:
    面积=cv2。轮廓面积(c)
    peri=cv2.弧长(c,真)
    近似值=cv2.近似聚合度(c,0.05*peri,真)
    如果len(近似值)=4且面积<100000:
    #cv2.等高线图(结果[c],-1,(36255,12),1)
    M=cv2.力矩(c)
    cx=int(M['m10']/M['m00']
    cy=int(M['m01']/M['m00']
    坐标。追加((cx,cy))
    cv2.圆(结果(cx,cy),3,(36255,12),-1)
    cv2.putText(result,({},{}).format(int(cx),int(cy)),(int(cx)-40,int(cy)-10),cv2.FONT\u HERSHEY\u SIMPLEX,0.5,(36255,12),2)
    打印(坐标)
    cv2.imshow('thresh',thresh)
    cv2.imshow(“图像”,图像)
    cv2.imshow(“结果”,结果)
    cv2.waitKey()
    
    你说瞬间不起作用。但您不显示代码。请始终提供您的代码,以便其他人可以看到您是否有错误。一旦你有了轮廓,你可以得到边界框,从中你可以很容易地计算出中心。不,对于瞬间,它给出零误差。这就是为什么我没有包括它你仍然没有显示你的质心代码。给定有效轮廓,您应该能够从以下位置获取质心:`M=cv2.矩(cntr)cx=int(M[“m10”]/M[“m00”])cy=int(M[“m01”]/M[“m00”])`
    import cv2
    import numpy as np
    
    # Load image, grayscale, Otsu's threshold
    image = cv2.imread('1.png')
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
    
    # Remove text
    cnts = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    for c in cnts:
        area = cv2.contourArea(c)
        if area < 1000:
            cv2.drawContours(thresh, [c], -1, 0, -1)
    
    thresh = 255 - thresh
    result = cv2.cvtColor(thresh, cv2.COLOR_GRAY2BGR)
    coordinates = []
    
    # Find rectangular boxes and obtain centroid coordinates
    cnts = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    for c in cnts:
        area = cv2.contourArea(c)
        peri = cv2.arcLength(c, True)
        approx = cv2.approxPolyDP(c, 0.05 * peri, True)
        if len(approx) == 4 and area < 100000:
            # cv2.drawContours(result, [c], -1, (36,255,12), 1)
            M = cv2.moments(c)
            cx = int(M['m10']/M['m00'])
            cy = int(M['m01']/M['m00'])
            coordinates.append((cx, cy))
            cv2.circle(result, (cx, cy), 3, (36,255,12), -1)
            cv2.putText(result, '({}, {})'.format(int(cx), int(cy)), (int(cx) -40, int(cy) -10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (36,255,12), 2)
    
    print(coordinates)
    cv2.imshow('thresh', thresh)
    cv2.imshow('image', image)
    cv2.imshow('result', result)
    cv2.waitKey()