1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        垃圾分類的正確姿勢(shì)?用 OpenCV 人工智能圖像識(shí)別技術(shù)來進(jìn)行

        共 9702字,需瀏覽 20分鐘

         ·

        2020-12-14 08:11


        點(diǎn)擊藍(lán)色“Python交流圈”關(guān)注我丫

        加個(gè)“星標(biāo)”,每天一起進(jìn)步一點(diǎn)點(diǎn)


        OpenCV是一款非常強(qiáng)大的圖像處理工具,對(duì)于從事圖像處理領(lǐng)域相關(guān)工作的人來說這個(gè)可以說是必不可少的一項(xiàng)工具,用起來也很方面,下嗎是一段簡(jiǎn)單的介紹:

        OpenCV是一個(gè)基于BSD許可(開源)發(fā)行的跨平臺(tái)計(jì)算機(jī)視覺和機(jī)器學(xué)習(xí)軟件庫,可以運(yùn)行在Linux、Windows、Android和Mac OS操作系統(tǒng)上。它輕量級(jí)而且高效——由一系列 C 函數(shù)和少量 C++ 類構(gòu)成,同時(shí)提供了Python、Ruby、MATLAB等語言的接口,實(shí)現(xiàn)了圖像處理和計(jì)算機(jī)視覺方面的很多通用算法。OpenCV用C++語言編寫,它具有C ++,Python,Java和MATLAB接口,并支持Windows,Linux,Android和Mac OS,OpenCV主要傾向于實(shí)時(shí)視覺應(yīng)用,并在可用時(shí)利用MMX和SSE指令, 如今也提供對(duì)于C#、Ch、Ruby,GO的支持。

        OpenCV官網(wǎng)是https://opencv.org/,首頁截圖如下所示:

        下面給出來幾個(gè)學(xué)習(xí)OpenCV的鏈接:
        https://docs.opencv.org/master/d9/df8/tutorial_root.html
        ?
        https://docs.opencv.org/
        ?
        https://www.zhihu.com/question/26881367
        我們今天的內(nèi)容主要是想基于OpenCV來實(shí)現(xiàn)對(duì)圖像中我們關(guān)注的一些目標(biāo)對(duì)象進(jìn)行檢測(cè)識(shí)別或者說是對(duì)其存在的區(qū)域位置進(jìn)行挖掘,在開始這篇文章之前,我曾經(jīng)看到了有人基于OpenCV實(shí)現(xiàn)了火焰或者是煙霧的檢測(cè),其實(shí)不管是類似的物體的檢測(cè)也好不相關(guān)的物體識(shí)別檢測(cè)也好,很大程度是比較通用的做法都是基于像素來完成最終的計(jì)算的。
        這里我們以生活中最為常見的土地來作為要識(shí)別檢測(cè)的目標(biāo)對(duì)象進(jìn)行實(shí)驗(yàn),先來看一張網(wǎng)上找到的圖片,如下所示:

        接下來先看一下,最終的識(shí)別檢測(cè)效果:

        從上面的結(jié)果來看,比較完全地檢測(cè)到了圖中出現(xiàn)的土地的區(qū)域,最終,我們采用外切矩形的方式完成了對(duì)其輪廓數(shù)據(jù)的確定。
        接下來,我們進(jìn)入正文,在實(shí)際去實(shí)踐之前,我們很有必要來了解一下幾種比較常用的顏色空間,簡(jiǎn)單總結(jié)匯總?cè)缦拢?/span>
        RGB顏色空間:
        R:Red?紅色
        G:Green?綠色
        B:Blue?藍(lán)色
        ?
        HSV顏色空間:
        H:Hue?色度
        S:Saturation?飽和度
        V:Value?亮度
        ?
        HSI顏色空間:
        H:Hue?色度
        S:Saturation?飽和度
        I:Intensity?強(qiáng)度
        本質(zhì)上來講,不同的物體不同的對(duì)象自身的像素范圍是不同的,在實(shí)際操作的時(shí)候基于像素區(qū)間可以過濾得到你所關(guān)注的對(duì)象,通常這樣的操作會(huì)在HSV空間中進(jìn)行,個(gè)人的理解是將原始的BGR或者是RGB的圖像轉(zhuǎn)化到HSV空間里面來確定目標(biāo)對(duì)象的像素區(qū)間更為容易,我實(shí)際測(cè)試過,在RGB和BGR空間里面也是可以進(jìn)行計(jì)算的,只不過不如HSV空間,這里就不再多討論了,可以嘗試別的方式,本文用的是HSV空間進(jìn)行計(jì)算的。
        最開始的時(shí)候去確定目標(biāo)對(duì)象所處的像素空間是很笨拙的,主要是借助OpenCV和matplotlib實(shí)現(xiàn)的“人眼探索”,比較麻煩,后來在github社區(qū)里面找到了一個(gè)界面的實(shí)現(xiàn),覺得很不錯(cuò),就拿來用了,這里貼出來源碼實(shí)現(xiàn),如下所示:
        #!usr/bin/env?python
        #?encoding:utf-8
        from?__future__?import?division
        ?
        '''
        功能:HSV空間圖片色素范圍查看器
        '''

        ?
        ?
        import?cv2
        import?numpy?as?np
        ?
        ?
        ?
        ?
        def?nothing(x):
        ????pass
        ?
        ?
        def?colorLooker(pic='1.png'):
        ????'''
        ????HSV空間圖片色素范圍查看器
        ????'''

        ????#圖像加載
        ????image?=?cv2.imread(pic)
        ????#窗口初始化
        ????cv2.namedWindow('image',cv2.WINDOW_NORMAL)
        ????#創(chuàng)建拖動(dòng)條
        ????#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)
        ????#設(shè)置默認(rèn)最大值
        ????cv2.setTrackbarPos('HMax',?'image',?179)
        ????cv2.setTrackbarPos('SMax',?'image',?255)
        ????cv2.setTrackbarPos('VMax',?'image',?255)
        ????#初始化設(shè)置
        ????hMin?=?sMin?=?vMin?=?hMax?=?sMax?=?vMax?=?0
        ????phMin?=?psMin?=?pvMin?=?phMax?=?psMax?=?pvMax?=?0
        ????while(1):
        ????????#實(shí)時(shí)獲取拖動(dòng)條上的值
        ????????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')
        ????????#設(shè)定HSV的最大和最小值
        ????????lower?=?np.array([hMin,?sMin,?vMin])
        ????????upper?=?np.array([hMax,?sMax,?vMax])
        ????????#BGR和HSV顏色空間轉(zhuǎn)化處理
        ????????hsv?=?cv2.cvtColor(image,?cv2.COLOR_BGR2HSV)
        ????????mask?=?cv2.inRange(hsv,?lower,?upper)
        ????????result?=?cv2.bitwise_and(image,?image,?mask=mask)
        ????????#拖動(dòng)改變閾值的同時(shí),實(shí)時(shí)輸出調(diào)整的信息
        ????????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
        ????????#展示由色素帶閾值范圍處理過的結(jié)果圖片
        ????????cv2.imshow('image',?result)
        ????????if?cv2.waitKey(10)?&?0xFF?==?ord('q'):
        ????????????break
        ????cv2.destroyAllWindows()
        ?
        ?
        ?
        ?
        if?__name__?==?'__main__':
        ????colorLooker(pic='1.png')
        ?
        ?
        啟動(dòng)后截圖如下所示:

        借助界面中的拖動(dòng)條可以很方便地進(jìn)行調(diào)節(jié),看到實(shí)時(shí)處理后的結(jié)果圖片:

        經(jīng)過調(diào)節(jié)后最終的結(jié)果如下所示:

        調(diào)整拖動(dòng)條的同時(shí),終端窗口輸出如下所示:

        到這里,我們已經(jīng)獲取到了所需要的各個(gè)維度的閾值數(shù)據(jù)了,就可以進(jìn)行后面的處理了。
        接下來我們基于上述閾值來進(jìn)行區(qū)域挖掘計(jì)算,同樣使用上述的圖片,核心代碼實(shí)現(xiàn)如下所示:
        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)
        #設(shè)置閾值數(shù)據(jù)
        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)
        之后為了得到實(shí)際的輪廓區(qū)域,我們可以使用cv2.findContours方法來實(shí)現(xiàn)目標(biāo)對(duì)象的區(qū)域挖掘計(jì)算,核心代碼實(shí)現(xiàn)如下所示:
        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中查找輪廓時(shí),物體應(yīng)該是白色而背景應(yīng)該是黑色
        contours,?hierarchy?=?cv2.findContours(image,mode,method)
        image:輸入圖像
        mode:輪廓的模式。cv2.RETR_EXTERNAL只檢測(cè)外輪廓;cv2.RETR_LIST檢測(cè)的輪廓不建立等級(jí)關(guān)系;cv2.RETR_CCOMP建立兩個(gè)等級(jí)的輪廓,上一層為外邊界,內(nèi)層為內(nèi)孔的邊界。如果內(nèi)孔內(nèi)還有連通物體,則這個(gè)物體的邊界也在頂層;cv2.RETR_TREE建立一個(gè)等級(jí)樹結(jié)構(gòu)的輪廓。
        method:輪廓的近似方法。cv2.CHAIN_APPROX_NOME存儲(chǔ)所有的輪廓點(diǎn),相鄰的兩個(gè)點(diǎn)的像素位置差不超過1;cv2.CHAIN_APPROX_SIMPLE壓縮水平方向、垂直方向、對(duì)角線方向的元素,只保留該方向的終點(diǎn)坐標(biāo),例如一個(gè)矩形輪廓只需要4個(gè)點(diǎn)來保存輪廓信息;cv2.CHAIN_APPROX_TC89_L1,cv2.CV_CHAIN_APPROX_TC89_KCOS
        contours:返回的輪廓
        hierarchy:每條輪廓對(duì)應(yīng)的屬性
        '''

        contours,hierarchy=cv2.findContours(output,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
        print('contours_num:?',?len(contours))
        count_dict={}
        areas,lengths=0,0
        for?i?in?range(len(contours)):
        ????one=contours[i]
        ????one_lk=one.tolist()
        ????if?len(one_lk)>=2:
        ????????area=cv2.contourArea(one)
        ????????length=cv2.arcLength(one,?True)
        ????????areas+=area
        ????????lengths+=length
        ????????left_list,right_list=[O[0][0]?for?O?in?one_lk],[O[0][1]?for?O?in?one_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=lambda?e:e[1][0],?reverse=True)
        print(sorted_list[:10])
        result['value']=count_dict
        cv2.drawContours(img,contours,-1,(0,0,255),3)
        完成輪廓的挖掘計(jì)算后,我們借助于OpenCV實(shí)現(xiàn)可視化,結(jié)果如下所示:

        可以看到:已經(jīng)大體上實(shí)現(xiàn)了我們所要的功能,但是美中不足的是里面有很多小的矩形框,這個(gè)是我們外切矩形設(shè)計(jì)的問題,沒有考慮到過濾掉嵌套或者是包含的情況,所以這里就來處理一下:
        if?sorted_list:
        ????filter_list=filterBox(sorted_list[:5])
        ????for?one_box?in?filter_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)
        此時(shí)的結(jié)果如下所示:

        對(duì)應(yīng)的計(jì)算結(jié)果輸出如下所示:
        ('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]])
        為了更加直觀地對(duì)比分析,我們將上面計(jì)算各個(gè)步驟中的對(duì)象數(shù)據(jù)進(jìn)行可視化,借助于matplotlib繪制在同一張圖上,結(jié)果如下所示:

        左上角為原始圖片,右下角為最終處理得到的圖片,可以看到整個(gè)處理過程的變化。
        到這里本文的內(nèi)容就結(jié)束了,學(xué)習(xí)依舊在路上,歡迎交流,互相學(xué)習(xí)!

        作者:沂水寒城,CSDN博客專家,個(gè)人研究方向:機(jī)器學(xué)習(xí)、深度學(xué)習(xí)、NLP、CV

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


        --End--


        近期熱門推薦?

        1、Python 游戲編程之實(shí)現(xiàn)飛機(jī)大戰(zhàn)(含源代碼)

        2、用 Hypothesis 快速測(cè)試你的 Python 代碼

        3、別這樣直接運(yùn)行Python命令,否則電腦等于“裸奔”

        4、太sao了吧!微信可以改彩色昵稱了?。。?/a>

        5、同步與異步 Python 有何不同?

        6、厲害了!手?jǐn)]一個(gè)微信訂閱號(hào)鑒黃機(jī)器人!用起來很可以!

        7、大廠的 404 頁面都長(zhǎng)啥樣?看到最后一個(gè),我笑了。。。

        8、爬取QQ音樂全部歌曲

        9、11 月全國(guó)程序員平均工資出爐,看你拉后退了沒

        10、用 Python 使用 Google Colab?豈止是炫酷

        關(guān)注公眾號(hào),回復(fù)“001”
        領(lǐng)取Python入門+進(jìn)階+實(shí)戰(zhàn)開發(fā)92天全套視頻教程


        點(diǎn)贊最大的支持?

        瀏覽 83
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            五月婷婷基地 | 肉逼网 | 日日躁狠狠躁夜夜躁A片图片 | 啊灬啊别停灬用力啊太深在线视频 | 亚洲国产日韩在线 | 国产免费看又黄又粗又硬 | 免费毛片一区二区三区亚女同 | 色婷婷在线精品视频 | 艹逼的视频 | 久久道 |