使用opencv分割图像(python实现)
- 概述
本人在做无人农机的时候需要进行图像处理,寻找目标物并进行分割,于是总结网络各种小车寻迹等等demo,自己也终于把图像颜色分割做的七七八八,特来记录一下,留作以后参考。 - 过程
import numpy as np
import cv2
- 读取图片(此处可以换成视频流,具体可以百度一下,原理相同,都是对一帧图片进行处理)
image = cv2.imread("C:/Users/92803/Downloads/1.jpg")
lower_blue = np.array([100,43,46])
upper_blue = np.array([124,255,255])
imgHSV = cv2.cvtColor(image,cv2.COLOR_BGR2HSV)
cv_image = cv2.inRange(imgHSV,lower_blue,upper_blue)
#cv_image已经是二值矩阵了
首先,图片从BGR格式转为HSV格式,因为RGB格式的图片在显示上非常方便,但是对于图像处理HSV格式是比较常用的,具体可以查看HSV格式和RGB格式的区别。 其次,cv2.inRange就是将HSV格式的图像进行二值化,在lower_blue和upper_blue之间的填充255,其余的都填充0。 具体各种颜色的值参考以下图片: 我以上填写的是过滤蓝色,填写对应的值就可以了。
- 过滤之后发现还有一些噪点,于是接着对图像进行腐蚀和膨胀:
#对图片进行腐蚀操作
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(10,10))
#这里的参数是选择卷积核的大小
cv_image = cv2.erode(cv_image,kernel)
#对图片进行膨胀操作
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(10,10))
cv_image = cv2.dilate(cv_image,kernel)
- 如果对结果还不满意,还可以对连通区域的面积进行过滤
contours,hie = cv2.findContours(cv_image,cv2.RETR_LIST,cv2.CHAIN_APPROX_NONE)
'''
调用函数发现图像中的连通区域,注意这里opencv3返回的是三个参数即image,contours,hie
contours与hie一一对应,根据findContours寻找的模式,contours可以找到连通区域的所有点轮廓,转折点轮廓等,此处是找所有点轮廓。
len(contours)返回的是连通区域的个数
'''
contours = np.array(contours,dtype=object)
#以上contours返回的是一个元组形式,转为ndarray格式,方便处理
index = 0
for contour in contours:
area = cv2.contourArea(contour)
#调用函数,求取连通区域面积(像素点个数)
if area < 10000:
#设置阈值
cv2.drawContours(cv_image,contour[np.newaxis,:],-1,(0,0,0),cv2.FILLED)
#对于面积小于10000像素的连通区域,进行填充黑色(本来是白色)
contours = np.delete(contours,index)
#从contours 中删除
index = index-1
#同时索引减1
index = index + 1
#自增1
for index,contour in enumerate(contours):
x,y,w,h = cv2.boundingRect(contour)
cv2.rectangle(cv_image,(x,y),(x+w,y+h),(139,35,35),5)
#对于面积大于等于10000连通区域在图像中画出矩形
对于为什么不放在一个for循环中,是因为有的连通预期画出矩形之后,然后填充面积不符合的区域,可能会把画的矩形框给擦除,所以分两步进行处理。
cv2.imshow("image",cv_image)
#这一步是必须的,不加会报错
cv2.waitKey(0)
参考资料: 1: cv2.findContours()函数 2:OpenCV-清除小面积连通域 3:HSV基本颜色分量范围 4:三分钟带你快速学习RGB、HSV和HSL颜色空间 5:cv2.inRange函数 ----------------------------------------分割线-----------------------------------------------------------------------
cv_image,contours,hierarchy = cv2.findContours(image=cv_image,mode=cv2.RETR_LIST,method=cv2.CHAIN_APPROX_NONE)
if len(contours)!=0:
contours2 = ()
for contour in contours:
area = cv2.contourArea(contour)
if area< 10000:
cv2.drawContours(cv_image,tuple([contour]),-1,(0,0,0),cv2.FILLED)
else:
contours2 = contours2 + tuple([contour])
for contour in contours2:
x,y,w,h = cv2.boundingRect(contour)
cv2.rectangle(cv_image,(x,y),(x+w,y+h),(139,35,35),5)
如果显示的是灰度图和ros进行转换要注意参数的设置
self.image_pub.publish(self.bridge.cv2_to_imgmsg(cv_image, "mono8"))
|