使用Python和OpenCV检测图像中的物体并将物体裁剪下来


Posted in Python onOctober 30, 2019

介绍

硕士阶段的毕设是关于昆虫图像分类的,代码写到一半,上周五导师又给我新的昆虫图片数据集了,新图片中很多图片很大,但是图片中的昆虫却很小,所以我就想着先处理一下图片,把图片中的昆虫裁剪下来,这样除去大部分无关背景,应该可以提高识别率。

原图片举例(将红色矩形框部分裁剪出来)):

使用Python和OpenCV检测图像中的物体并将物体裁剪下来

step1:加载图片,转成灰度图

image = cv2.imread("353.jpg")
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)

# subtract the y-gradient from the x-gradient
gradient = cv2.subtract(gradX, gradY)
gradient = cv2.convertScaleAbs(gradient)

执行完这一步,得到的图像如下:

使用Python和OpenCV检测图像中的物体并将物体裁剪下来

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)

执行完这一步,得到的图像如下:

使用Python和OpenCV检测图像中的物体并将物体裁剪下来

step4:在上图中我们看到蜜蜂身体区域有很多黑色的空余,我们要用白色填充这些空余,使得后面的程序更容易识别昆虫区域,这需要做一些形态学方面的操作。

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (25, 25))
closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)

处理之后的图像如下:

使用Python和OpenCV检测图像中的物体并将物体裁剪下来

step5:从上图我们发现图像上还有一些小的白色斑点,这会干扰之后的昆虫轮廓的检测,要把它们去掉。分别执行4次形态学腐蚀与膨胀。

# perform a series of erosions and dilations
closed = cv2.erode(closed, None, iterations=4)
closed = cv2.dilate(closed, None, iterations=4)

执行完这步,得到的图形如下:

使用Python和OpenCV检测图像中的物体并将物体裁剪下来

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()函数:
主要求得包含点集最小面积的矩形,这个矩形是可以有偏转角度的,可以与图像的边界不平行。

(cnts, _) = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
c = sorted(cnts, key=cv2.contourArea, reverse=True)[0]

# compute the rotated bounding box of the largest contour
rect = cv2.minAreaRect(c)
box = np.int0(cv2.cv.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)

执行完这步得到的图形如下:

使用Python和OpenCV检测图像中的物体并将物体裁剪下来

step7:裁剪。box里保存的是绿色矩形区域四个顶点的坐标。我将按下图红色矩形所示裁剪昆虫图像。找出四个顶点的x,y坐标的最大最小值。新图像的高=maxY-minY,宽=maxX-minX。

使用Python和OpenCV检测图像中的物体并将物体裁剪下来

Xs = [i[0] for i in box]
Ys = [i[1] for i in box]
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]

裁剪出的图片如下:

使用Python和OpenCV检测图像中的物体并将物体裁剪下来

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中使用select模块实现非阻塞的IO
Feb 03 Python
Python中的高级函数map/reduce使用实例
Apr 13 Python
python strip() 函数和 split() 函数的详解及实例
Feb 03 Python
基于python的Tkinter编写登陆注册界面
Jun 30 Python
scrapy爬虫完整实例
Jan 25 Python
OPENCV去除小连通区域,去除孔洞的实例讲解
Jun 21 Python
python读取文本中的坐标方法
Oct 14 Python
使用Python向C语言的链接库传递数组、结构体、指针类型的数据
Jan 29 Python
python字典嵌套字典的情况下找到某个key的value详解
Jul 10 Python
python新式类和经典类的区别实例分析
Mar 23 Python
什么是Python中的匿名函数
Jun 02 Python
python pip如何手动安装二进制包
Sep 30 Python
python基于K-means聚类算法的图像分割
Oct 30 #Python
Python列表原理与用法详解【创建、元素增加、删除、访问、计数、切片、遍历等】
Oct 30 #Python
Python文件路径名的操作方法
Oct 30 #Python
Python元组 tuple的概念与基本操作详解【定义、创建、访问、计数、推导式等】
Oct 30 #Python
解决python 上传图片限制格式问题
Oct 30 #Python
Python字典的概念及常见应用实例详解
Oct 30 #Python
Python集合基本概念与相关操作实例分析
Oct 30 #Python
You might like
PHP 手机归属地查询 api
2010/02/08 PHP
PHP中数组合并的两种方法及区别介绍
2012/09/14 PHP
数组与类使用PHP的可变变量名需要的注意的问题
2013/06/20 PHP
php实现专业获取网站SEO信息类实例
2015/04/02 PHP
PHP获取某个月最大天数(最后一天)的方法
2015/07/29 PHP
PHP面向对象程序设计实例分析
2016/01/26 PHP
PHP的微信支付接口使用方法讲解
2019/03/08 PHP
Jquery iframe内部出滚动条
2010/02/11 Javascript
JQuery EasyUI 对话框的使用方法
2010/10/24 Javascript
Jquery上传插件 uploadify v3.1使用说明
2012/06/18 Javascript
IE6下opacity与JQuery的奇妙结合
2013/03/01 Javascript
jquery判断元素是否隐藏的多种方法
2014/05/06 Javascript
Javascript 拖拽的一些简单的应用(逐行分析代码,让你轻松了拖拽的原理)
2015/01/23 Javascript
Underscore.js 1.3.3 中文注释翻译说明
2015/06/25 Javascript
JavaScript实现简单获取当前网页网址的方法
2015/11/09 Javascript
详解JavaScript中|单竖杠运算符的使用方法
2016/05/23 Javascript
使用ajaxfileupload.js实现上传文件功能
2016/08/13 Javascript
jQuery实现鼠标悬停3d菜单展开动画效果
2017/01/19 Javascript
three.js快速入门【推荐】
2017/01/21 Javascript
Vue报错:Uncaught TypeError: Cannot assign to read only property’exports‘ of object’#‘的解决方法
2017/06/17 Javascript
vue中v-text / v-html使用实例代码详解
2019/04/02 Javascript
python文件和目录操作函数小结
2014/07/11 Python
numpy找出array中的最大值,最小值实例
2018/04/03 Python
关于pycharm中pip版本10.0无法使用的解决办法
2019/10/10 Python
python飞机大战pygame碰撞检测实现方法分析
2019/12/17 Python
基于virtualenv创建python虚拟环境过程图解
2020/03/30 Python
使用python无账号无限制获取企查查信息的实例代码
2020/04/17 Python
Python sorted对list和dict排序
2020/06/09 Python
Selenium及python实现滚动操作多种方法
2020/07/21 Python
一款利用html5和css3实现的3D滚动特效的教程
2015/01/04 HTML / CSS
草莓网英国官网:Strawberrynet UK
2017/02/12 全球购物
Vita Fede官网:在意大利手工制作,在纽约市设计
2019/10/25 全球购物
高一军训的心得体会
2014/09/01 职场文书
代收款委托书范本
2014/10/01 职场文书
Python连续赋值需要注意的一些问题
2021/06/03 Python
Golang入门之计时器
2022/05/04 Golang