0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于OpenCV来实现对图像中目标对象检测识别 以土地为例

新机器视觉 来源:http://yishuihancheng.blog.csd 作者:沂水寒城 2020-11-23 16:33 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

OpenCV是一款非常强大的图像处理工具,对于从事图像处理领域相关工作的人来说这个可以说是必不可少的一项工具,用起来也很方面,下吗是一段简单的介绍:

OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。OpenCV用C++语言编写,它具有C ++,Python,Java和MATLAB接口,并支持Windows,Linux,Android和Mac OS,OpenCV主要倾向于实时视觉应用,并在可用时利用MMX和SSE指令, 如今也提供对于C#、Ch、Ruby,GO的支持。

OpenCV官网是https://opencv.org/,首页截图如下所示:

下面给出来几个学习OpenCV的链接:

https://docs.opencv.org/master/d9/df8/tutorial_root.html https://docs.opencv.org/ https://www.zhihu.com/question/26881367我们今天的内容主要是想基于OpenCV来实现对图像中我们关注的一些目标对象进行检测识别或者说是对其存在的区域位置进行挖掘,在开始这篇文章之前,我曾经看到了有人基于OpenCV实现了火焰或者是烟雾的检测,其实不管是类似的物体的检测也好不相关的物体识别检测也好,很大程度是比较通用的做法都是基于像素来完成最终的计算的。 这里我们以生活中最为常见的土地来作为要识别检测的目标对象进行实验,先来看一张网上找到的图片,如下所示:

接下来先看一下,最终的识别检测效果:

从上面的结果来看,比较完全地检测到了图中出现的土地的区域,最终,我们采用外切矩形的方式完成了对其轮廓数据的确定。 接下来,我们进入正文,在实际去实践之前,我们很有必要来了解一下几种比较常用的颜色空间,简单总结汇总如下:

RGB颜色空间: R:Red红色 G:Green绿色 B:Blue蓝色 HSV颜色空间: H:Hue色度 S:Saturation饱和度 V:Value亮度 HSI颜色空间: H:Hue色度 S:Saturation饱和度 I:Intensity强度本质上来讲,不同的物体不同的对象自身的像素范围是不同的,在实际操作的时候基于像素区间可以过滤得到你所关注的对象,通常这样的操作会在HSV空间中进行,个人的理解是将原始的BGR或者是RGB的图像转化到HSV空间里面来确定目标对象的像素区间更为容易,我实际测试过,在RGB和BGR空间里面也是可以进行计算的,只不过不如HSV空间,这里就不再多讨论了,可以尝试别的方式,本文用的是HSV空间进行计算的。 最开始的时候去确定目标对象所处的像素空间是很笨拙的,主要是借助OpenCV和matplotlib实现的“人眼探索”,比较麻烦,后来在github社区里面找到了一个界面的实现,觉得很不错,就拿来用了,这里贴出来源码实现,如下所示:#!usr/bin/envpython #encoding:utf-8 from__future__importdivision ''' 功能:HSV空间图片色素范围查看器 ''' importcv2 importnumpyasnp defnothing(x): pass defcolorLooker(pic='1.png'): ''' HSV空间图片色素范围查看器 ''' #图像加载 image=cv2.imread(pic) #窗口初始化 cv2.namedWindow('image',cv2.WINDOW_NORMAL) #创建拖动条 #Opencv中Hue取值范围是0-179 cv2.createTrackbar('HMin','image',0,179,nothing) cv2.createTrackbar('SMin','image',0,255,nothing) cv2.createTrackbar('VMin','image',0,255,nothing) cv2.createTrackbar('HMax','image',0,179,nothing) cv2.createTrackbar('SMax','image',0,255,nothing) cv2.createTrackbar('VMax','image',0,255,nothing) #设置默认最大值 cv2.setTrackbarPos('HMax','image',179) cv2.setTrackbarPos('SMax','image',255) cv2.setTrackbarPos('VMax','image',255) #初始化设置 hMin=sMin=vMin=hMax=sMax=vMax=0 phMin=psMin=pvMin=phMax=psMax=pvMax=0 while(1): #实时获取拖动条上的值 hMin=cv2.getTrackbarPos('HMin','image') sMin=cv2.getTrackbarPos('SMin','image') vMin=cv2.getTrackbarPos('VMin','image') hMax=cv2.getTrackbarPos('HMax','image') sMax=cv2.getTrackbarPos('SMax','image') vMax=cv2.getTrackbarPos('VMax','image') #设定HSV的最大和最小值 lower=np.array([hMin,sMin,vMin]) upper=np.array([hMax,sMax,vMax]) #BGR和HSV颜色空间转化处理 hsv=cv2.cvtColor(image,cv2.COLOR_BGR2HSV) mask=cv2.inRange(hsv,lower,upper) result=cv2.bitwise_and(image,image,mask=mask) #拖动改变阈值的同时,实时输出调整的信息 if((phMin!=hMin)|(psMin!=sMin)|(pvMin!=vMin)|(phMax!=hMax)|(psMax!=sMax)|(pvMax!=vMax)): print("(hMin=%d,sMin=%d,vMin=%d),(hMax=%d,sMax=%d,vMax=%d)"%(hMin,sMin,vMin,hMax,sMax,vMax)) phMin=hMin psMin=sMin pvMin=vMin phMax=hMax psMax=sMax pvMax=vMax #展示由色素带阈值范围处理过的结果图片 cv2.imshow('image',result) ifcv2.waitKey(10)&0xFF==ord('q'): break cv2.destroyAllWindows() if__name__=='__main__': colorLooker(pic='1.png') 启动后截图如下所示:

借助界面中的拖动条可以很方便地进行调节,看到实时处理后的结果图片:

经过调节后最终的结果如下所示:

调整拖动条的同时,终端窗口输出如下所示:

到这里,我们已经获取到了所需要的各个维度的阈值数据了,就可以进行后面的处理了。 接下来我们基于上述阈值来进行区域挖掘计算,同样使用上述的图片,核心代码实现如下所示:

img=Image.open('1.png') img=cv2.cvtColor(np.asarray(img),cv2.COLOR_RGB2BGR) frame=cv2.cvtColor(img,cv2.COLOR_BGR2HSV) blur=cv2.GaussianBlur(frame,(21,21),0) hsv=cv2.cvtColor(blur,cv2.COLOR_BGR2HSV) h,w,way=img.shape total=h*w print('h:',h,'w:',w,'area:',total) #设置阈值数据 lower=[8,67,84] upper=[85,255,255] lower=np.array(lower,dtype="uint8") upper=np.array(upper,dtype="uint8") mask=cv2.inRange(hsv,lower,upper) output=cv2.bitwise_and(hsv,hsv,mask=mask) count=cv2.countNonZero(mask) print('count:',count) now_ratio=round(int(count)/total,3) print('now_ratio:',now_ratio)

之后为了得到实际的轮廓区域,我们可以使用cv2.findContours方法来实现目标对象的区域挖掘计算,核心代码实现如下所示:gray=cv2.cvtColor(output,cv2.COLOR_BGR2GRAY) print('gray_shape:',gray.shape) ret,output=cv2.threshold(gray,127,255,cv2.THRESH_BINARY) ''' cv2.findContours:
在opencv中查找轮廓时,物体应该是白色而背景应该是黑色 contours,hierarchy=cv2.findContours(image,mode,method) image:输入图像 mode:轮廓的模式。cv2.RETR_EXTERNAL只检测外轮廓;cv2.RETR_LIST检测的轮廓不建立等级关系;cv2.RETR_CCOMP建立两个等级的轮廓,上一层为外边界,内层为内孔的边界。如果内孔内还有连通物体,则这个物体的边界也在顶层;cv2.RETR_TREE建立一个等级树结构的轮廓。 method:轮廓的近似方法。cv2.CHAIN_APPROX_NOME存储所有的轮廓点,相邻的两个点的像素位置差不超过1;cv2.CHAIN_APPROX_SIMPLE压缩水平方向、垂直方向、对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需要4个点来保存轮廓信息;cv2.CHAIN_APPROX_TC89_L1,cv2.CV_CHAIN_APPROX_TC89_KCOS contours:返回的轮廓 hierarchy:每条轮廓对应的属性 ''' contours,hierarchy=cv2.findContours(output,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) print('contours_num:',len(contours)) count_dict={} areas,lengths=0,0 foriinrange(len(contours)): one=contours[i] one_lk=one.tolist() iflen(one_lk)>=2: area=cv2.contourArea(one) length=cv2.arcLength(one,True) areas+=area lengths+=length left_list,right_list=[O[0][0]forOinone_lk],[O[0][1]forOinone_lk] minX,maxX,minY,maxY=min(left_list),max(left_list),min(right_list),max(right_list) A=abs(maxY-minY)*abs(maxX-minX) print('area:',area,'A:',A,'length:',length) count_dict[i]=[A,area,length,[minX,maxX,minY,maxY]] sorted_list=sorted(count_dict.items(),key=lambdae:e[1][0],reverse=True) print(sorted_list[:10]) result['value']=count_dict cv2.drawContours(img,contours,-1,(0,0,255),3)完成轮廓的挖掘计算后,我们借助于OpenCV实现可视化,结果如下所示:

可以看到:已经大体上实现了我们所要的功能,但是美中不足的是里面有很多小的矩形框,这个是我们外切矩形设计的问题,没有考虑到过滤掉嵌套或者是包含的情况,所以这里就来处理一下:

ifsorted_list: filter_list=filterBox(sorted_list[:5]) forone_boxinfilter_list: print('one_box:',one_box) A,area,length,[minX,maxX,minY,maxY]=one_box cv2.rectangle(img,(minX,maxY),(maxX,minY),(0,255,0),3)此时的结果如下所示:

对应的计算结果输出如下所示:

('h:',336L,'w:',500L,'area:',168000L) ('count:',126387) ('now_ratio:',0.752) ('output_shape:',(336L,500L,3L)) ('gray_shape:',(336L,500L)) ('contours_num:',64) ('area:',0.0,'A:',2,'length:',4.828427076339722) ('area:',0.0,'A:',0,'length:',4.0) ('area:',29.0,'A:',44,'length:',27.313708186149597) ('area:',42.5,'A:',72,'length:',34.72792184352875) ('area:',0.5,'A:',6,'length:',9.071067690849304) ('area:',0.0,'A:',10,'length:',11.656854152679443) ('area:',0.0,'A:',1,'length:',2.8284270763397217) ('area:',0.0,'A:',2,'length:',4.828427076339722) ('area:',1.5,'A:',2,'length:',5.414213538169861) ('area:',16.5,'A:',36,'length:',27.55634891986847) ('area:',5.0,'A:',36,'length:',37.79898953437805) ('area:',1.5,'A:',3,'length:',8.242640614509583) ('area:',0.0,'A:',0,'length:',2.0) ('area:',2.0,'A:',2,'length:',6.0) ('area:',360.0,'A:',1026,'length:',206.93607211112976) ('area:',44.0,'A:',143,'length:',59.94112479686737) ('area:',0.0,'A:',1,'length:',2.8284270763397217) ('area:',0.0,'A:',1,'length:',2.8284270763397217) ('area:',33.5,'A:',60,'length:',30.38477599620819) ('area:',76.5,'A:',228,'length:',63.35533845424652) ('area:',320.0,'A:',792,'length:',166.9949471950531) ('area:',16.0,'A:',35,'length:',21.313708305358887) ('area:',0.0,'A:',8,'length:',10.828427076339722) ('area:',21.0,'A:',78,'length:',37.79898953437805) ('area:',0.0,'A:',1,'length:',2.8284270763397217) ('area:',0.0,'A:',2,'length:',4.828427076339722) ('area:',0.0,'A:',2,'length:',4.828427076339722) ('area:',3.5,'A:',25,'length:',20.727921843528748) ('area:',1.5,'A:',12,'length:',13.071067690849304) ('area:',51.0,'A:',121,'length:',53.94112491607666) ('area:',0.0,'A:',1,'length:',2.8284270763397217) ('area:',32.5,'A:',50,'length:',27.899494767189026) ('area:',309.5,'A:',722,'length:',96.32590079307556) ('area:',34.0,'A:',42,'length:',22.485281229019165) ('area:',80970.5,'A:',132699,'length:',2718.5739262104034) [(63,[132699,80970.5,2718.5739262104034,[1,498,67,334]]),(24,[1026,360.0,206.93607211112976,[33,60,281,319]]),(39,[792,320.0,166.9949471950531,[61,94,252,276]]),(61,[722,309.5,96.32590079307556,[384,422,75,94]]),(34,[228,76.5,63.35533845424652,[1,13,267,286]]),(25,[143,44.0,59.94112479686737,[68,81,280,291]]),(55,[121,51.0,53.94112491607666,[189,200,219,230]]),(47,[78,21.0,37.79898953437805,[100,113,235,241]]),(4,[72,42.5,34.72792184352875,[209,221,328,334]]),(32,[60,33.5,30.38477599620819,[15,25,274,280]])] ('one_box:',[132699,80970.5,2718.5739262104034,[1,498,67,334]])为了更加直观地对比分析,我们将上面计算各个步骤中的对象数据进行可视化,借助于matplotlib绘制在同一张图上,结果如下所示:

左上角为原始图片,右下角为最终处理得到的图片,可以看到整个处理过程的变化。 到这里本文的内容就结束了,学习依旧在路上,欢迎交流,互相学习!

作者:沂水寒城,CSDN博客专家,个人研究方向:机器学习、深度学习、NLP、CV

Blog:http://yishuihancheng.blog.csdn.net

责任编辑:PSY

原文标题:垃圾分类的正确姿势?用 OpenCV 人工智能图像识别技术来进行

文章出处:【微信公众号:新机器视觉】欢迎添加关注!文章转载请注明出处。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 图像识别
    +关注

    关注

    9

    文章

    529

    浏览量

    39847
  • 检测识别
    +关注

    关注

    0

    文章

    9

    浏览量

    7348
  • OpenCV
    +关注

    关注

    33

    文章

    651

    浏览量

    44430

原文标题:垃圾分类的正确姿势?用 OpenCV 人工智能图像识别技术来进行

文章出处:【微信号:vision263com,微信公众号:新机器视觉】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    技术分享 | RK3588基于Yolov5的目标识别演示

    YOLO是一种基于深度神经网络的目标检测算法,用在图像或视频实时识别和定位多个对象。在其各个版
    的头像 发表于 09-18 17:27 1055次阅读
    技术分享 | RK3588基于Yolov5的<b class='flag-5'>目标识别</b>演示

    如何使用树莓派与OpenCV实现面部和运动追踪的云台系统?

    使用树莓派和OpenCV实时扫描并存储二维码使用树莓派和OpenCV实现物体与动物识别使用树莓派、摄像头和OpenCV进行速度
    的头像 发表于 08-14 17:45 982次阅读
    如何使用树莓派与<b class='flag-5'>OpenCV</b><b class='flag-5'>实现</b>面部和运动追踪的云台系统?

    如何使用树莓派+OpenCV实现姿态估计和面部特征点追踪?

    使用树莓派和OpenCV实时扫描并存储二维码使用树莓派和OpenCV实现物体与动物识别使用树莓派、摄像头和OpenCV进行速度
    的头像 发表于 08-13 17:44 991次阅读
    如何使用树莓派+<b class='flag-5'>OpenCV</b><b class='flag-5'>实现</b>姿态估计和面部特征点追踪?

    【Milk-V Duo S 开发板免费体验】SDK编译、人脸检测OpenCV测试

    -mobile-test ./opencv-mobile-test 生成 200x200 尺寸的 out.jpg 图像,即实现图片压缩。 该测试工程可结合物体识别模型,
    发表于 07-11 13:48

    基于LockAI视觉识别模块:C++人脸识别

    基本知识讲解 1.1 人脸识别简介 人脸识别是一种利用人的脸部特征进行身份识别的生物识别技术。它通过检测
    发表于 07-01 12:01

    基于LockAI视觉识别模块:手写数字识别

    (input_mat); 作用:PaddleClas类的一个函数,用于实现手写数字识别。 参数说明: input_mat:要识别图像
    发表于 06-30 16:45

    基于LockAI视觉识别模块:C++目标检测

    检测是计算机视觉领域中的一个关键任务,它不仅需要识别图像存在哪些对象,还需要定位这些对象的位置
    发表于 06-06 14:43

    基于LockAI视觉识别模块:C++条码识别

    (input_mat); 作用:Code128Detector类的一个函数,用于实现条码识别。 参数说明: input_mat: 要识别图像
    发表于 05-27 10:26

    基于LockAI视觉识别模块:C++二维码识别

    实现二维码识别。 参数说明: input_mat: 输入参数,类型cv::Mat,表示要分析的输入图像。 返回值: 返回一个包含二维码检测
    发表于 05-26 09:57

    基于LockAI视觉识别模块:C++轮廓检测

    基本知识讲解 1.1 图像处理的重要性 目标检测图像处理技术可以用于检测图像
    发表于 05-22 10:05

    基于LockAI视觉识别模块:C++图像的基本运算

    图像处理,理解图像的基本操作是掌握计算机视觉技术的关键。本文章将介绍 基于LockAI视觉识别模块下OpenCV
    发表于 05-06 16:56

    基于LockAI视觉识别模块:C++图像采集例程

    OpenCV 实现摄像头模块的视频流读取与图像传输。核心步骤包括: 初始化摄像头并设置分辨率; 打开摄像头并逐帧捕获图像; 使用 Edit 模块进行
    发表于 04-30 10:52

    LSDK构建opencv时遇到的问题求解

    我正在尝试使用 flex-builder 运行 bld -c opencv -r ubuntu:桌面 我想要最新版本的 OpenCV。在我的 sdk.yml 文件,我将
    发表于 03-26 08:26

    AI模型部署边缘设备的奇妙之旅:目标检测模型

    分类任务是识别图像主体内容的是什么?的问题,那么目标检测则是进一步解答在哪里? 目标
    发表于 12-19 14:33

    AI模型部署边缘设备的奇妙之旅:如何在边缘端部署OpenCV

    直线、圆等)的技术,它通过参数空间的投票机制实现。对于圆形检测,Hough变换可以识别出满足特定条件的圆形结构。下面是使用 OpenCV
    发表于 12-14 09:31