Python 如何根据颜色测量房间的大小

Python 如何根据颜色测量房间的大小,python,opencv,image-processing,Python,Opencv,Image Processing,因此,该代码能够将它标识的各种房间分割成不同的颜色,如下所示。问题是,如何获得彩色房间的面积(如蓝色房间)。房间按1m:150m的比例布置 第一个图像是我需要测量的输出,第二个房间是我用来运行代码的图像,第三个图像是供参考的原始图像。提前谢谢 import numpy as np def find_rooms(img, noise_reduction=10, corners_threshold=0.0000001, room_close=2, gap_in_wal

因此,该代码能够将它标识的各种房间分割成不同的颜色,如下所示。问题是,如何获得彩色房间的面积(如蓝色房间)。房间按1m:150m的比例布置

第一个图像是我需要测量的输出,第二个房间是我用来运行代码的图像,第三个图像是供参考的原始图像。提前谢谢

import numpy as np

def find_rooms(img, noise_reduction=10, corners_threshold=0.0000001,
               room_close=2, gap_in_wall_threshold=0.000001):

    # :param img: grey scale image of rooms, already eroded and doors removed etc.
    # :param noise_reduction: Amount of noise removed.
    # :param corners_threshold: Corners to retained, higher value = more of house removed.
    # :param room_close: Maximum line length to add to close off open doors.
    # :param gap_in_wall_threshold: Minimum number of pixels to identify component as room instead of hole in the wall.
    # :return: rooms: list of numpy arrays containing boolean masks for each detected room
    # colored_house: Give room a color.

    assert 0 <= corners_threshold <= 1
    # Remove noise left from door removal

    img[img < 128] = 0
    img[img > 128] = 255
    contours, _ = cv2.findContours(~img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    mask = np.zeros_like(img)
    for contour in contours:
        area = cv2.contourArea(contour)
        if area > noise_reduction:
            cv2.fillPoly(mask, [contour], 255)

    img = ~mask

    # Detect corners (you can play with the parameters here)
    #harris corner detection
    dst = cv2.cornerHarris(img, 4,3,0.000001)
    dst = cv2.dilate(dst,None)
    corners = dst > corners_threshold * dst.max()

    # Draw lines to close the rooms off by adding a line between corners on the same x or y coordinate
    # This gets some false positives.
    # Can try disallowing drawing through other existing lines, need to test.
    for y,row in enumerate(corners):
        x_same_y = np.argwhere(row)
        for x1, x2 in zip(x_same_y[:-1], x_same_y[1:]):

            if x2[0] - x1[0] < room_close:
                color = 0
                cv2.line(img, (x1, y), (x2, y), color, 1)

    for x,col in enumerate(corners.T):
        y_same_x = np.argwhere(col)
        for y1, y2 in zip(y_same_x[:-1], y_same_x[1:]):
            if y2[0] - y1[0] < room_close:
                color = 0
                cv2.line(img, (x, y1), (x, y2), color, 1)


    # Mark the outside of the house as black
    contours, _ = cv2.findContours(~img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contour_sizes = [(cv2.contourArea(contour), contour) for contour in contours]
    biggest_contour = max(contour_sizes, key=lambda x: x[0])[1]
    mask = np.zeros_like(mask)
    cv2.fillPoly(mask, [biggest_contour], 255)
    img[mask == 0] = 0

    # Find the connected components in the house
    ret, labels = cv2.connectedComponents(img)
    img = cv2.cvtColor(img,cv2.COLOR_GRAY2RGB)
    unique = np.unique(labels)
    rooms = []
    for label in unique:
        component = labels == label
        if img[component].sum() == 0 or np.count_nonzero(component) < gap_in_wall_threshold:
            color = 0
        else:
            rooms.append(component)
            color = np.random.randint(0, 255, size=3)
        img[component] = color

    return rooms, img

#Read gray image
img = cv2.imread('output16.png', 0)
rooms, colored_house = find_rooms(img.copy())
cv2.imshow('result', colored_house)
cv2.waitKey()
cv2.destroyAllWindows()
将numpy导入为np
def查找房间(img,降噪=10,角点阈值=0.0000001,
房间关闭=2,墙壁中的间隙=0.000001):
#:param img:房间的灰度图像,已腐蚀,门已拆除等。
#:param noise_reduction:去除的噪声量。
#:param corners_threshold:要保留的角,值越高=移除的房屋越多。
#:param room_close:关闭打开的门所需添加的最大线条长度。
#:param gap_in_wall_threshold:将构件标识为房间而不是墙中的孔的最小像素数。
#:return:rooms:包含每个检测到的房间的布尔掩码的numpy数组列表
#彩色房子:给房间一个颜色。
断言0降噪:
cv2.fillPoly(掩模,[轮廓],255)
img=~面具
#检测角点(您可以在此处使用参数)
#哈里斯角点检测
dst=cv2.0(img,4,3,0.000001)
dst=cv2.扩张(dst,无)
角点=dst>角点_阈值*dst.max()
#通过在相同x或y坐标的角点之间添加一条线来绘制线以关闭房间
#这会得到一些误报。
#可以尝试禁止通过其他现有线绘制,需要测试。
对于y,枚举中的行(角点):
x_same_y=np.argwhere(行)
对于压缩中的x1,x2(x_same_y[:-1],x_same_y[1:]):
如果x2[0]-x1[0]<房间关闭:
颜色=0
cv2.线(img,(x1,y)、(x2,y),颜色,1)
对于x,枚举中的列(corners.T):
y_same_x=np.argwhere(col)
对于邮政编码中的y1、y2(y_same_x[:-1],y_same_x[1:]):
如果y2[0]-y1[0]<房间关闭:
颜色=0
cv2.线(img,(x,y1),(x,y2),颜色,1)
#把房子外面标记为黑色
等高线,u=cv2.查找等高线(~img,cv2.RETR\u外部,cv2.CHAIN\u近似值\u简单值)
轮廓尺寸=[(cv2.轮廓面积(轮廓),轮廓)用于轮廓中的轮廓]
最大轮廓=最大(轮廓尺寸,键=λx:x[0])[1]
掩码=np.类零(掩码)
cv2.fillPoly(掩模,[最大轮廓],255)
img[mask==0]=0
#找到房子里连接的部件
ret,标签=cv2。连接组件(img)
img=cv2.cvt颜色(img,cv2.COLOR\u GRAY2RGB)
唯一=np.唯一(标签)
房间=[]
对于唯一的标签:
组件=标签==标签
如果img[component].sum()==0或np.count\u非零(component)
好的,假设您使用OpenCV阅读分割的图片:

import cv2
import numpy as np

# reading the segmented picture in coloured mode
image = cv2.imread("path/to/segmented/coloured/picture.jpg", cv2.IMREAD_COLOR)
现在,假设您知道整个图片的大小(以平方米为单位),例如,如果图片反射的总面积为150m x 70m,则总面积为150x70=10500m²。让我们将其声明为一个变量:

total_size = 10500
您还想知道图片中的像素总数。例如,如果您的图片是750*350像素,则您有:262500像素。您可以通过以下方式实现:

total_number_of_pixels = image.shape[0]*image.shape[1]
现在,正如我在评论中所说,您还想知道分割图片中每个独特颜色的像素数,您可以使用:

# count all occurrences of unique colours in your picture
unique, counts = np.unique(image.reshape(-1, image.shape[2]), axis=0, return_counts=True)

coloured_pixel_counts = sorted(zip(unique, counts), key=lambda x: x[1]))
现在,你所要做的就是一个交叉乘法,可以用这样的方法来完成:

rooms = []
for colour, pixel_count in coloured_pixel_counts:
     rooms.append((colour, (pixel_count/total_number_of_pixels)*total_size))
您现在应该有一份所有颜色的列表,以及该颜色房间的相应近似大小(以平方米为单位)

现在,请注意,但是,您可能必须将此列表子集为您感兴趣的颜色,因为在您分割的图片中,有些颜色似乎并没有真正链接到房间


请再次询问是否有任何不清楚的地方

因此测量将基于像素,您需要知道要“测量”的颜色的RGB值的最大和最小范围。我在您的图像上运行此代码,以查找绿色区域占整个房屋面积的百分比,结果如下:

过滤后的像素数为:331213,占房屋面积的%5


计算给定颜色的像素是否可行?比如,如果你有以米为单位的整个图片的尺寸,你可以简单地计算一种颜色的像素数与图片中像素总数的比率?它可能不精确,但由于图像分割很少,我认为它可以工作?我想是的,但我如何让它测量所有房间,并指出紫色房间是x m^2,蓝色房间是y m^2?好的,对于分割图像中的每种不同颜色,你计算图片中该颜色的像素数,然后你把这个数字除以图片中的像素总数,这样就得到了一个比率。然后,乘以图片的总尺寸(以平方米为单位)!你想让我发布一个更清楚的答案吗?我想这会很有帮助,因为我大致了解了测量长度的工作原理,但我不确定如何让它告诉我测量属于哪个房间。谢谢为了澄清,我需要定义什么是形状吗?因为它告诉我什么是未定义的。它到底在哪里说它是未定义的呢?哦,等等,我的糟糕,大脑今天工作得不太好,哈哈,是吗
import cv2
import numpy as np
import math

img = cv2.imread('22I7X.png')
#Defining wanted color range
filteredColorMin = np.array([36,0,0], np.uint8) #Min range
filteredColorMax = np.array([70, 255,255], np.uint8) #High range
#Find all the pixels in the wanted color range
dst = cv2.inRange(img, filteredColorMin, filteredColorMax)
#count non-zero values from filtered range
numFilteredColor = cv2.countNonZero(dst)
#Getting total number of pixels in image to get the percentage of the filtered pixels from the total pixels
numTotalPixels=img.shape[0] *img.shape[1]

print('The number of filtered pixels is: ' + str(numFilteredColor) + " Which counts for %" + str(math.ceil((numFilteredColor/numTotalPixels)*100)) + " of the house")
cv2.imshow("original image",img)
cv2.waitKey(0)