基于opencv的簡單影像輪廓形狀識別**(全網最簡單最少代碼)!!!**
可以直接跳到最后整體代碼看一看是不是很少的代碼!!!!
思路:
1. 資料的整合
2. 圖片的灰度轉化
3. 圖片的二值轉化
4. 圖片的輪廓識別
5. 得到圖片的頂點數
6. 依據頂點數判斷影像形狀
一、原資料的展示

圖片檔案共36個檔案夾,每個檔案夾有100張圖片,共3600張圖片,

每一個檔案夾里都有形同此類的圖形
二、資料的整合
對于多個檔案夾,分析起來很不方便,所有決定將其都放在一個檔案夾下進行分析,在python中具體實作如下:
本次需要的包
import cv2
import os
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
a=os.listdir('C:\\Users\\dell\\Desktop\\OpenCVProofSet')#回圈讀取每個子檔案夾
for i in range(len(a)):
b=os.listdir('C:\\Users\\dell\\Desktop\\OpenCVProofSet\\'+a[i])#讀取每個子檔案下的圖片檔案
for j in range(len(b)):
c=Image.open('C:\\Users\\dell\\Desktop\\OpenCVProofSet\\'+a[i]+'\\'+b[j])#回圈讀取每個圖片檔案
c.save('C:\\Users\\dell\\Desktop\\cleardata\\'+str(i)+'_'+str(j)+'.png')#以檔案夾序號和圖片序號為名保存在一個興建檔案夾下
結果如下:

三、圖片輪廓的確定
3.1圖片的灰度處理
以下以一張圖片為例子作為說明
對于灰度的處理,選擇使用opencv的cv2.cvtColor函式,代碼示例如下:
d=os.listdir('C:\\Users\\dell\\Desktop\\cleardata\\')#檔案路徑
e=cv2.imread('C:\\Users\\dell\\Desktop\\cleardata\\'+d[5])#以矩陣的形式圖片讀入
plt.imshow(e)#畫出示例圖

進行灰度的轉化:
g=cv2.cvtColor(e,cv2.COLOR_BGR2GRAY)##灰度轉化
3.2圖片的二值轉化
對于圖片的二值轉化這里選用cv2.threshold函式,代碼示例如下:
r,b=cv2.threshold(g,0,255,cv2.THRESH_OTSU)#二值轉化,大于0的像素統一設定為255,小于等于0的統一設定為0
上述代碼的第一個引數為灰度圖形,第二個引數是閾值,即大于0的像素點轉化為255,然后選用的THRESH_OTSU方法,具體說明如下:
通常情況,我們一般不知道設定怎樣的閾值thresh才能得到比較好的二值化效果,只能去試,如對于一幅雙峰影像(理解為影像直方圖中存在兩個峰),我們指定的閾值應盡量在兩個峰之間的峰谷,這時,就可以用第四個引數THRESH_OTSU,它對一幅雙峰影像自動根據其直方圖計算出合適的閾值(對于非雙峰圖,這種方法得到的結果可能不理想),
對于雙峰圖,我們需要多傳入一個引數cv2.THRESH_OTSU,并且把閾值thresh設為0,演算法會找到最優閾值,并作為第一個回傳值ret回傳,
其中會回傳兩個值,第二個值就是二值化后的圖形矩陣,
3.3輪廓的尋找
在輪廓的尋找方面,采用cv2.findContours方式,代碼示例如下:
cr,t=cv2.findContours(b, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)##找到邊界,第一個引數是二值影像,第二個引數是獲取輪廓的方式,
#第三個引數定義輪廓的近似方式
上述函式里的引數中,第一個引數是二值化后的矩陣,第二個引數是獲取輪廓的方式,第三個引數是定義輪廓的近似方式,后面兩個引數的具體解釋如下:

上面得到的結果中第一個結果是輪廓點的集合,
畫出邊界輪廓,運用函式是cv2.drawContours,代碼示例如下:
plt.imshow(cv2.drawContours(e,cr,-1,50))#畫出邊界,可以看出有坐標軸和五角星兩個邊界,第一個引數是原圖,第二個引數是邊界,
#第三個引數代表畫出所有邊界,第四個引數是線的粗細
上述函式中第一個引數是原始圖形,第二個引數是得到的輪廓點的集合,第三個引數是代表畫出所有輪廓點,第四個引數是線的粗細,
得到結果如下:

可以發現,坐標軸的輪廓和五角星的輪廓都被畫了出來,
3.4輪廓的逼近,得到頂點
在得到輪廓點后,需要得到輪廓的頂點,通過頂點得到具體什么圖形,在輪廓逼近中用到兩個函式:cv2.arcLength,cv2.approxPolyDP,代碼示例如下:
ep = 0.01*cv2.arcLength(cr[1], True)#五角星輪廓的周長cr[0]是坐標軸的周長,然后將其縮小,作為下一步的閾值
ap = cv2.approxPolyDP(cr[1], ep, True)#輪廓的轉折點的近似點
cv2.arcLength得到的是輪廓點形成的曲線圍成的圖形的周長,cr[1]代表里層五角星的輪廓點,因為cr里有兩個輪廓集合,一個是外層的坐標軸的輪廓點集合,一個是里層五角星的輪廓點集合,True代表閉合的曲線,將其取1%作為下一個函式的閾值,
cv2.approxPolyDP將其得到的輪廓點進行篩選(按設定的閾值與其真實的線進行比較),其篩選的標準就是上一個函式得到的1%的周長,大于這個值的點舍去,小于這個值的點保留,True依然代表閉合曲線,

通過以上的步驟就可以保留一些點,而這些點就是得到頂點(這點需要讀者去想一想,為什么以1%周長為閾值得到的點就是頂點,作者認為是兩條線的拐點相對于來說是里真實線最近的點)
頂點數:
len(ap)#可以看見五角星有10個點

四、依據頂點判斷形狀
根據得到的定點數就可判斷出形狀了,三個頂點就是三角形,四個就是矩形,十個就是五角星,十個以上就是圓形了;上述的完整代碼如下:
import cv2
import os
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
d=os.listdir('C:\\Users\\dell\\Desktop\\cleardata\\')
for i in range(len(d)):
e=cv2.imread('C:\\Users\\dell\\Desktop\\cleardata\\'+d[i])
g=cv2.cvtColor(e,cv2.COLOR_BGR2GRAY)
r,b=cv2.threshold(g,0,255,cv2.THRESH_OTSU)
cr,t=cv2.findContours(b, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
ep = 0.01*cv2.arcLength(cr[1], True)
ap = cv2.approxPolyDP(cr[1], ep, True)
co=len(ap)
if co==3:
st='三角形'
elif co==4:
st='矩形'
elif co==10:
st='五角星'
else:
st='圓'
plt.imsave('C:\\Users\\dell\\Desktop\\形狀\\'+st+str(e[100][100])+str(i)+'.jpg',e)#取影像中間的點的RGB作為顏色代表
這里我還取了圖形的中點,希望得到圖片的顏色,其得到的是RGB值,通過RGB值就可以得到顏色,
最終結果如下:




End.
謝謝大家,其間借鑒許多大佬的文章,不勝感激!!!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/253486.html
標籤:python
上一篇:爬蟲神器scrapy的安裝
