python CV 图形面积计算

遍历目录图片,实现:
1.标识出图片的颜色,
2.蓝色边框标识出方格区域(10*10),
3.标识出油漆脱落的小方格数量(小正方形10%脱落,认为该区该小正方形整个脱落)占方格区域的数量(一般是100)比例和实际脱落面积比例(需扣除划痕面积)。
4.用文字在图片上标识出有脱落面积的比例。
2285657249@qq.com(可QQ交流)
注意:示例图片脱落不明显,可手动修改照片,以实现测试效果。

img

img

img

①10×10是小格数量,每个小格是2mm或1.5mm见方,面积不用真实值,用像素点也可以。②面漆的颜色大部分是黄色,有时是灰色(统一按黄色考虑)。底漆的颜色不一定是白色,大部分是灰色或红色。③可以考虑通过颜色的变化来进行脱落的识别。④补充一下比较明显脱落的照片。

img

img

这个单位是多少,比如10×10是毫米?

有几个疑问:
1、你这图片估计不是原图吧,现在宽是320像素,你所谓的10*10是按什么单位来计算的?
2、方格区域的数量(一般是100)是说要把图片分割成100个方格,然后去计算每个方格的脱落情况吗
3、实际脱落面积比例是说不考虑方格的问题,只考虑脱落区域(不规则)占整个图片的比例吗

这个不太会啊

这个有意思,但是有些地方不够完善,掉漆的位置一定是白色的吗?如果里面有底漆,导致掉漆呈现红色,或者照片里反光,都是会误识别的,这个怎么算

  • 只要表面颜色与其它颜色不相同,就算脱落吗?
  • 如果一半脱落,一半未脱落,那么就存在2种颜色,哪种颜色算脱落?

你说的10乘以10的小方格是像素吗,还是有其它单位?漆脱落的小方格数量占方格区域的数量为什么一般是100?不太明白。

标王啊,看来要学一下OpenCV了

识别油漆脱落点,还要判断不是反光的地方,有点儿难哦。

opencv库应该可以跑,不过朋友的硬件是打算用什么?openmv还是树莓派官方摄像头还是OV7725

这个单位是多少

使用cv处理,hsv颜色识别,然后框选出脱落的面积,使用are算子提取,即可。

像素和实面积是多少啊还是自己假设啊,如果是摄像机要考虑,不同拍摄角度距离,后不同的比例

对于这个问题,色彩分水岭似乎是一个很好的方法.
当你解决这个问题时,定义标记的前景和背景是困难的部分!
建议使用形态梯度沿着破坏面积获得良好的边缘。
第一步:

import numpy as np

import cv2

img = cv2.imread('image.png')

blur = cv2.GaussianBlur(img, (7, 7), 2)

h, w = img.shape[:2]

# Morphological gradient

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7, 7))

gradient = cv2.morphologyEx(blur, cv2.MORPH_GRADIENT, kernel)

cv2.imshow('Morphological gradient', gradient)

cv2.waitKey()

第二步:使用一些阈值来对梯度进行二值化

lowerb = np.array([0, 0, 0])

upperb = np.array([15, 15, 15])

binary = cv2.inRange(gradient, lowerb, upperb)

cv2.imshow('Binarized gradient', binary)

cv2.waitKey()

第三步:遍历边缘上的像素并使用floodFill()从二进制图像中删除多余部分

for row in range(h):

if binary[row, 0] == 255:

cv2.floodFill(binary, None, (0, row), 0)

if binary[row, w-1] == 255:

cv2.floodFill(binary, None, (w-1, row), 0)

for col in range(w):

if binary[0, col] == 255:

cv2.floodFill(binary, None, (col, 0), 0)

if binary[h-1, col] == 255:

cv2.floodFill(binary, None, (col, h-1), 0)

cv2.imshow('Filled binary gradient', binary)

cv2.waitKey()

第四步:清理

foreground = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel)

foreground = cv2.morphologyEx(foreground, cv2.MORPH_CLOSE, kernel)

cv2.imshow('Cleanup up crystal foreground mask', foreground)

cv2.waitKey()

第五步:获得被破坏图像

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (17, 17))

background = cv2.dilate(foreground, kernel, iterations=3)

unknown = cv2.subtract(background, foreground)

cv2.imshow('Background', background)

cv2.waitKey()


第六步:标记分界线

markers = cv2.connectedComponents(foreground)[1]

markers += 1 # Add one to all labels so that background is 1, not 0

markers[unknown==255] = 0 # mark the region of unknown with zero

markers = cv2.watershed(img, markers)

第七步:标记块

hue_markers = np.uint8(179*np.float32(markers)/np.max(markers))

blank_channel = 255*np.ones((h, w), dtype=np.uint8)

marker_img = cv2.merge([hue_markers, blank_channel, blank_channel])

marker_img = cv2.cvtColor(marker_img, cv2.COLOR_HSV2BGR)

cv2.imshow('Colored markers', marker_img)

cv2.waitKey()

第八步:与原始图像对比

labeled_img = img.copy()

labeled_img[markers>1] = marker_img[markers>1] # 1 is background color

labeled_img = cv2.addWeighted(img, 0.5, labeled_img, 0.5, 0)

cv2.imshow('watershed_result.png', labeled_img)

cv2.waitKey()


最后:计算面积
.


import math

class Round(): #圆形

def __init__(self, R):

self.R = R

def area(self):

return self.R * self.R * 3.14

def girth(self):

return self.R * 2 * 3.14

class Rectangle():#矩形

def __init__(self, length, width):

self.length = length

self.width = width

def area(self):

return self.length * self.width

def girth(self):

return self.length + self.width

class Triangle():#三角形

def __init__(self, a, b, c):

self.a = a

self.b = b

self.c = c

def area(self):

l = (self.a + self.b + self.c)/2

return round(math.sqrt(l * (l - self.a) * (l - self.b) * (l - self.c)), 2) #round保留2为小数

def girth(self):

return self.a + self.c + self.c

class Guadrilateral():#任意四边形

def __init__(self, a, b, c, d, angle):

self.a = a

self.b = b

self.c = c

self.d = d

self.angle = angle

def area(self):

l = (self.a + self.b + self.c + self.d)/2

return round(math.sqrt((l - self.a) * (l - self.b) * (l - self.c) * (l - self.d) -

self.a * self.b * self.c * self.d

* math.pow(math.cos(math.radians(self.angle)), 2)), 2) #pow函数幂次方radians弧度转换为角度

def girth(self):

return self.a + self.b + self.c + self.d

print("----图形计算工具----")

print("*******************")

print("***你可以选择的图形***")

print("********圆形********")

print("********矩形********")

print("*******三角形********")

print("*****任意四边形*******")

target = str(input("请输入你想要计算图形的名称"))

if target == "圆形":

x1 = int(input("请输入半径(厘米):"))

print("圆形的面积为:" + str(Round(x1).area()) + "(平方厘米)!")

print("圆形的周长为:" + str(Round(x1).girth()) + "(厘米)!")

elif target == "矩形":

x1 = int(input("请输入长度(厘米):"))

x2 = int(input("请输入宽度(厘米):"))

print("矩形的面积为:" + str(Rectangle(x1, x2).area()) + "(平方厘米)!")

print("矩形的周长为:" + str(Rectangle(x1, x2).girth()) + "(厘米)!")

elif target == "三角形":

x1 = int(input("请输入边a(厘米):"))

x2 = int(input("请输入边b(厘米):"))

x3 = int(input("请输入边c(厘米):"))

print("三角形的面积为:" + str(Triangle(x1, x2, x3).area()) + "(平方厘米)!")

print("三角形的周长为:" + str(Triangle(x1, x2, x3).girth()) + "(厘米)!")

elif target == "任意四边形":

x1 = int(input("请输入边a(厘米):"))

x2 = int(input("请输入边b(厘米):"))

x3 = int(input("请输入边c(厘米):"))

x4 = int(input("请输入边d(厘米):"))

x5 = int(input("请输入邻对角角度和的一半(°):"))

print("三角形的面积为:" + str(Guadrilateral(x1, x2, x3, x4, x5).area()) + "(平方厘米)!")

print("三角形的周长为:" + str(Guadrilateral(x1, x2, x3, x4, x5).girth()) + "(厘米)!")