机器学习基础之 opencv应用检测图像
import numpy as np
import cv2 

'''
使用Python和OpenCV检测图像中的物体并将物体裁剪下来(画框) 
把图片中的昆虫裁剪下来,这样除去大部分无关背景,可提高识别率。:
step1:加载图片,转成灰度图 (类似 ps-图像-去色)
	使用png图片时,报错 libpng warning: iCCP: known incorrect sRGB profile
	虽不影响程序运行,但这个警告是和png图片的格式有关。可以用相应方法解决
'''
image = cv2.imread("pic_1.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

'''
step2:用 Sobel算子 计算x,y方向上的梯度,
之后在x方向上减去y方向上的梯度,通过这个减法,留下具有高水平梯度和低垂直梯度的图像区域。

gradX = cv2.Sobel(gray, ddepth=cv2.cv.CV_32F, dx=1, dy=0, ksize=-1)
gradY = cv2.Sobel(gray, ddepth=cv2.cv.CV_32F, dx=0, dy=1, ksize=-1)
报错:AttributeError: module 'cv2' has no attribute 'cv'
'''
gradX = cv2.Sobel(gray, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1)
gradY = cv2.Sobel(gray, ddepth=cv2.CV_32F, dx=0, dy=1, ksize=-1)

# subtract the y-gradient from the x-gradient
gradient = cv2.subtract(gradX, gradY)
gradient = cv2.convertScaleAbs(gradient)
# print( gradient )
'''
[[  0 255  16 ...  20 255   0]
 [ 94 255   0 ...  40 255 112]
 [ 92 255  58 ...  26 255  92]
 ...
 [255 255 255 ... 255 255 255]
 [204 255 255 ... 148  90 204]
 [  0 118 102 ... 102 118   0]]
'''

# 执行完这一步,得到的图像( pic_2.png )
'''
step3:去除图像上的噪声。首先使用低通滤泼器平滑图像(9 x 9内核),
这将有助于平滑图像中的高频噪声。低通滤波器的目标是降低图像的变化率。
如将每个像素替换为该像素周围像素的均值。这样就可以平滑并替代那些强度变化明显的区域。

然后,对模糊图像二值化。梯度图像中不大于90的任何像素都设置为0(黑色)。 否则,像素设置为255(白色)。
'''
# blur and threshold the image
blurred = cv2.blur(gradient, (9, 9))
(_, thresh) = cv2.threshold(blurred, 90, 255, cv2.THRESH_BINARY) # threshold 阈值,门槛,临界值
## 执行完这一步,得到的图像( pic_3.png )

'''
step4:在上图中我们看到蜜蜂身体区域有很多黑色的空余,
我们要用白色填充这些空余,使得后面的程序更容易识别昆虫区域,这需要做一些形态学方面的操作。
'''
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (25, 25))
closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
## 执行完这一步,得到的图像( pic_4.png )
'''
step5:从上图我们发现图像上还有一些小的白色斑点,这会干扰之后的昆虫轮廓的检测,
要把它们去掉。分别执行4次形态学腐蚀与膨胀。
'''
# perform a series of erosions and dilations
closed = cv2.erode(closed, None, iterations=4)
closed = cv2.dilate(closed, None, iterations=4)
## 执行完这一步,得到的图像( pic_5.png )

'''
step6:找出昆虫区域的轮廓。
cv2.findContours()函数来查找检测物体的轮廓。
    第一个参数是要检索的图片,必须是为二值图,即黑白的(不是灰度图),
        所以读取的图像要先转成灰度的,再转成二值图,
        在第三步用cv2.threshold()函数已经得到了二值图。

    第二个参数表示轮廓的检索模式,有四种:
        cv2.RETR_EXTERNAL 表示只检测外轮廓
        cv2.RETR_LIST 检测的轮廓不建立等级关系
        cv2.RETR_CCOMP 建立两个等级的轮廓,上面一层为外边界,
            里面一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。
        cv2.RETR_TREE 建立一个等级树结构的轮廓。

    第三个参数为轮廓的近似方法
        cv2.CHAIN_APPROX_NONE存储所有的轮廓点,相邻的两个点的像素位置差不超过1,
            即max(abs(x1-x2),abs(y2-y1))==1
        cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,
            例如一个矩形轮廓只需4个点来保存轮廓信息
        cv2.findContours()函数返回两个值,一个是轮廓本身,还有一个是每条轮廓对应的属性。
        cv2.findContours()函数返回第一个值是list,list中每个元素都是图像中的一个轮廓,

用numpy中的ndarray表示。每一个ndarray里保存的是轮廓上的各个点的坐标。
把list排序,点最多的那个轮廓就是要找的昆虫的轮廓。

OpenCV中通过cv2.drawContours在图像上绘制轮廓。
    第一个参数是指明在哪幅图像上绘制轮廓
    第二个参数是轮廓本身,在Python中是一个list
    第三个参数指定绘制轮廓list中的哪条轮廓,如果是-1,则绘制其中的所有轮廓
    第四个参数是轮廓线条的颜色
    第五个参数是轮廓线条的粗细

cv2.minAreaRect()函数:
主要求得包含点集最小面积的矩形,这个矩形是可以有偏转角度的,可以与图像的边界不平行。
'''
get_findContours = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
'''
使用cv2.findContours()函数来查找检测物体的轮廓。
get_findContours = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
程序报错:too many values to unpack (expected 2) # ValueError:打开太多值(预期2)
错误原因:由于版本问题 cv2.findContours返回值个数发生变化,调用len(a)发现长度为3,
第一个,返回了所处理的图像(高版本新增的)
第二个,轮廓的点集(老版本的第一个)
第三个,各层轮廓的索引(老版本的第二个)
'''
# print( len(args_) ) # 3
(orgin_obj , cnts, _) = get_findContours
c = sorted(cnts, key=cv2.contourArea, reverse=True)[0]

# compute the rotated bounding box of the largest contour
rect = cv2.minAreaRect(c)
print( 'rect = ' , rect )
'''
rect =  ((500.49993896484375, 298.9999694824219), (1000.9998779296875, 375.99993896484375), -0.0)
'''

'''
做到旋转的边界矩形时,box = np.int0(cv2.cv.BoxPoints(rect))函数
报错 AttributeError: module 'cv2' has no attribute 'cv'

改为 box = np.int0(cv2.BoxPoints(rect))
报错 AttributeError: module 'cv2' has no attribute 'BoxPoints'
#因为,改为首字母小写了 cv2.boxPoints(rect)
'''
# help(cv2.boxPoints)
box = np.int0(cv2.boxPoints(rect))

# draw a bounding box arounded the detected barcode and display the image
cv2.drawContours(image, [box], -1, (0, 255, 0), 3)
cv2.imshow("Image", image)
cv2.imwrite("contoursImage2.jpg", image)
cv2.waitKey(0)
## 执行完这一步,得到的图像( pic_6.png )
'''
step7:裁剪。
box里保存的是绿色矩形区域四个顶点的坐标。将按下图红色矩形所示裁剪昆虫图像。
找出四个顶点的x,y坐标的最大最小值。新图像的高=maxY-minY,宽=maxX-minX。
## 执行完这一步,得到的图像( pic_7.png )
'''
print(box)
'''
[[424 439]
 [213 197]
 [403  30]
 [614 272]]
'''
Xs = [i[0] for i in box]
Ys = [i[1] for i in box]
print(Xs) # [424, 213, 403, 614]
print(Ys) # [439, 197, 30, 272]

x1 = min(Xs)
x2 = max(Xs)
y1 = min(Ys)
y2 = max(Ys)
hight = y2 - y1
width = x2 - x1
cropImg = image[y1:y1 + hight, x1:x1 + width]
'''
## 执行完这一步,得到的图像( pic_8_last.png )
'''


本实例来源于网络,经过添加备注和修改bug,测试后,运行正常。原图如下:

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SecondLieutenant/article/details/79970539
个人分类: 机器学习
所属专栏: Code36行,基础为王
想对作者说点什么? 我来说一句

opencv火焰检测识别

2017年10月17日 18.53MB 下载

OpenCV的图像模糊与否检测

2017年10月17日 11.52MB 下载

没有更多推荐了,返回首页

不良信息举报

机器学习基础之 opencv应用检测图像

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭