经历了一个月的opencv的学习,首先我要推荐一本学习opencv很有用的书《opencv轻松面向python》。我在做下面的这个项目的时候基本是看这个书的。
下面先介绍我所做的图像识别的内容:
这是一个工厂的四个炉口,我要做的任务是识别炉口中放了几个材料。通过肉眼观察我们知道一共有三个材料。
我对这个图像识别的步骤大致如下:1.对图像进行高斯滤波,消去图像的噪声。
2.对图像进行灰度化。(因为我下面要对图像进行二值化,二值化的目标图像是灰度图)
3.对图像进行二值化。
4.进行开运算,它是一个先腐蚀后膨胀的过程。开运算可以用来消除小黑点,在纤细点处分离物体、平滑较大物体的边界的 同时并不明显改变其面积。(做完这一步图像可能没什么变化,就是觉得高级,单纯的想加上)
5.关键一步,进行腐蚀操作,这样消除一些白色的小方块。
代码如下:
1.导入库,读取图片,显示图片
显示出的图片:
2.对图片进行一系列的操作:
I=cv2.imread('D:\\opencv\\4w.png')
img_Guassian=cv2.GaussianBlur(I,(5,5),0) #高斯滤波,去除图片中的噪声
gray=cv2.cvtColor(img_Guassian,cv2.COLOR_BGR2GRAY) #灰度化图像
thre,bw=cv2.threshold(gray,245,255,cv2.THRESH_BINARY) #对图片进行二值化操作
#二值化后,进行形态学操作(开运算,腐蚀+膨胀),去除细小干扰
kernel=np.ones((7,7),np.uint8) #设置形态学操作卷积核大小
opening=cv2.morphologyEx(bw,cv2.MORPH_OPEN,kernel)
cv2.imshow('opening',opening) #查看形态学操作后的结果并展示
cv2.waitKey(0)
cv2.destroyAllWindows()
#腐蚀
kernels=np.ones((6,6),np.uint8)
erosion=cv2.erode(opening,kernels,iterations=2)#后面iterations是迭代的次数,我让它迭代两次。
imshow(erosion)
腐蚀过后图片变为:
到这一步我们应该就要考虑改如何让计算机识别材料的个数。
我采用面积的方法来计算材料的个数。计算出空白处没有材料的面积,计算这个面积占整个炉口的面积的比例,通过这种方法我们可以得出材料的个数。
3.识别轮廓
#得到轮廓contours
contours,hir=cv2.findContours(erosion,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
# 检测所有轮廓,所有轮廓建立一个等级树结构。外层轮廓包含内层轮廓,内层轮廓还可以继续包含内嵌轮廓。
result = cv2.drawContours(I, contours, -1, (0, 255, 0), 3) #利用得到的轮廓信息,将轮廓绘制出
imshow(result)
这张图片绿色线画出的联通区域是识别出来的轮廓。
4.计算轮廓的面积
n=len(contours)#n是轮廓的个数
contoursImg=[]
for i in range(n)://用一个循环语句计算出四个轮廓的面积
print("contours["+str(i)+"]面积=",cv2.contourArea(contours[i]))
temp=np.zeros(I.shape,np.uint8)
contoursImg.append(temp)
contoursImg[i]=cv2.drawContours(contoursImg[i],contours,i,(255,255,255),3)
cv2.imshow("contours["+str(i)+"]",contoursImg[i])
#在这里我让他单独显示出了每个轮廓的形状,方便观看。
cv2.waitKey()
cv2.destroyAllWindows()
四个轮廓的面积:
contours[0]面积= 15600.5 contours[1]面积= 3574.5 contours[2]面积= 16329.5 contours[3]面积= 14834.5
5.识别材料的个数
首先我们要通过数学的计算,算出2和3炉口的面积。
一个材料的窄侧的横截面积=第三个轮廓的面积-第二个轮廓的面积
2炉口的面积=3炉口的面积=第三个轮廓的面积+一个材料窄侧的横截面积
#手算可得2和三的炉口面积为:29084.5
#一个材料的面积:12755
for i in range(n):
im_count = 0
if i==0 or i== 3: # 第1,4个炉口
im_ratio=cv2.contourArea(contours[i])/15600.5
if im_ratio>0.6:
im_count=0
else:
im_count=1
elif i==1 or i==2: # 第2,3个炉口
im_ratio=cv2.contourArea(contours[i])/29084.5
if im_ratio >0.57:
im_count = 0
elif im_ratio>0.13 and im_ratio<=0.57:
im_count = 1
elif im_ratio<=0.13:
im_count=2
print('第{}个炉口的材料的个数为:{}'.format(i+1,im_count))
最后的答案是:
第1个炉口的材料的个数为:0 第2个炉口的材料的个数为:2 第3个炉口的材料的个数为:1 第4个炉口的材料的个数为:0