1 簡(jiǎn)介
Opencv(Open Source Computer Vision Library)是一個(gè)基于開(kāi)源發(fā)行的跨平臺(tái)計(jì)算機(jī)視覺(jué)庫(kù),它實(shí)現(xiàn)了圖像處理和計(jì)算機(jī)視覺(jué)方面的很多通用算法,已成為計(jì)算機(jī)視覺(jué)領(lǐng)域最有力的研究工具。在深度學(xué)習(xí)中,我們會(huì)經(jīng)常接觸到兩個(gè)名稱,圖像處理和計(jì)算機(jī)視覺(jué),它們之間有什么區(qū)別呢?圖像處理 (Image Processing)
目的:圖像處理主要集中在改善或轉(zhuǎn)換圖像的質(zhì)量,使得圖像更適合人類觀察或者為后續(xù)的分析做準(zhǔn)備。
方法:通常涉及像素級(jí)別的操作,比如調(diào)整亮度、對(duì)比度、顏色校正、濾波(如高斯模糊、中值濾波去噪)、邊緣檢測(cè)、形態(tài)學(xué)變換(膨脹、腐蝕)等。
計(jì)算機(jī)視覺(jué) (Computer Vision)
目的:計(jì)算機(jī)視覺(jué)的目標(biāo)是使計(jì)算機(jī)能夠理解和解釋圖像或視頻的內(nèi)容,實(shí)現(xiàn)類似于人類視覺(jué)系統(tǒng)的感知能力。
方法:使用高級(jí)算法來(lái)解析圖像中的內(nèi)容,包括但不限于特征提取、物體識(shí)別、分類、跟蹤、場(chǎng)景重建等。這可能涉及到機(jī)器學(xué)習(xí)和深度學(xué)習(xí)模型的應(yīng)用。
簡(jiǎn)而言之,圖像處理是計(jì)算機(jī)視覺(jué)的基礎(chǔ),提供了必要的工具和技術(shù)來(lái)預(yù)處理和優(yōu)化圖像數(shù)據(jù);而計(jì)算機(jī)視覺(jué)則是在此基礎(chǔ)之上,通過(guò)更加復(fù)雜的算法和模型來(lái)解析圖像的意義。在實(shí)際應(yīng)用中,這兩者往往是緊密結(jié)合的,共同作用于解決復(fù)雜的問(wèn)題。例如,在一個(gè)自動(dòng)駕駛系統(tǒng)中,圖像處理可能會(huì)用于清理傳感器輸入的數(shù)據(jù),而計(jì)算機(jī)視覺(jué)則負(fù)責(zé)識(shí)別道路上的行人、車輛和其他重要元素。
2 基礎(chǔ)知識(shí)
OpenCV 是一個(gè)開(kāi)源的計(jì)算機(jī)視覺(jué)和機(jī)器學(xué)習(xí)軟件庫(kù),廣泛用于圖像處理、視頻捕捉、物體檢測(cè)等領(lǐng)域。一些常用操作及其目的:
讀取圖片
使用cv2.imread()函數(shù)加載圖像。
目的:為后續(xù)處理和分析準(zhǔn)備圖像數(shù)據(jù)。
轉(zhuǎn)換色彩空間
使用cv2.cvtColor()進(jìn)行色彩空間轉(zhuǎn)換。
目的:適應(yīng)不同算法的需求,例如灰度圖用于簡(jiǎn)化計(jì)算,HSV用于顏色分割等。
濾波
高斯模糊 (cv2.GaussianBlur)、均值濾波 (cv2.blur) 和雙邊濾波 (cv2.bilateralFilter) 等。
目的:降噪和平滑圖像,或在保持邊緣的同時(shí)模糊細(xì)節(jié)。
繪制圖形
使用cv2.line()、cv2.rectangle()、cv2.circle()和cv2.polylines()來(lái)繪制直線、矩形、圓形或多邊形。
目的:可視化結(jié)果,標(biāo)注圖像中的特征或者創(chuàng)建掩碼。
邊緣檢測(cè)
Canny 邊緣檢測(cè) (cv2.Canny) 或 Sobel 操作符 (cv2.Sobel)。
目的:檢測(cè)圖像中物體的邊界,是很多高級(jí)計(jì)算機(jī)視覺(jué)任務(wù)的基礎(chǔ)步驟。
閾值操作
cv2.threshold()用于二值化圖像。
目的:突出顯示感興趣區(qū)域,簡(jiǎn)化圖像以利于進(jìn)一步分析。
Sobel 濾波
使用cv2.Sobel()計(jì)算圖像梯度。
目的:增強(qiáng)邊緣,通常與邊緣檢測(cè)相關(guān)聯(lián)。
文件保存
cv2.imwrite()將圖像保存到磁盤(pán)。
目的:保存處理后的圖像以便將來(lái)使用或分享。
此外,還有其他重要的OpenCV功能,如:
直方圖均衡化(cv2.equalizeHist) 提升圖像對(duì)比度。
模板匹配(cv2.matchTemplate) 用于查找一個(gè)圖像中的另一個(gè)小圖像的位置。
特征點(diǎn)檢測(cè)和描述子計(jì)算,如 SIFT, SURF, ORB 等,用于圖像配準(zhǔn)、拼接等任務(wù)。
這些基礎(chǔ)操作和高級(jí)特性共同構(gòu)成了強(qiáng)大的工具集,可以用來(lái)開(kāi)發(fā)從簡(jiǎn)單的圖像編輯應(yīng)用到復(fù)雜的計(jì)算機(jī)視覺(jué)系統(tǒng)。 這些操作是構(gòu)建復(fù)雜圖像處理流水線的基礎(chǔ),可以單獨(dú)使用,也可以組合起來(lái)解決更復(fù)雜的視覺(jué)問(wèn)題。例如,預(yù)處理階段可能會(huì)包括去噪、邊緣檢測(cè)和形態(tài)學(xué)操作;而在后處理階段,則可能會(huì)涉及閾值操作和繪制幾何圖形來(lái)標(biāo)注或解釋結(jié)果。以上這些算子僅僅是OpenCV庫(kù)的一小部分的內(nèi)容,但是它們是支持我們進(jìn)行復(fù)雜操作的基礎(chǔ)。
3 實(shí)際操作
在學(xué)習(xí)OpenCV的初期,可能會(huì)覺(jué)得每個(gè)算子或函數(shù)就像是獨(dú)立的知識(shí)點(diǎn),雖然能夠理解它們各自的功能和用法,但當(dāng)面對(duì)實(shí)際問(wèn)題時(shí),卻難以將這些知識(shí)點(diǎn)有效地組合起來(lái)解決問(wèn)題。這是因?yàn)閺睦碚摰綄?shí)踐的應(yīng)用需要一個(gè)過(guò)渡的過(guò)程,在這個(gè)過(guò)程中,不僅需要掌握單個(gè)算子的操作,還需要學(xué)會(huì)如何根據(jù)具體的需求選擇合適的算子,并且合理地調(diào)整參數(shù)以達(dá)到預(yù)期的效果。OpenCV的強(qiáng)大之處在于它提供了豐富的圖像處理功能,但這也意味著使用它的難點(diǎn)在于:
理解和記憶大量的算子:OpenCV庫(kù)中包含了大量的算子,每個(gè)算子都有其特定的應(yīng)用場(chǎng)景和參數(shù)設(shè)置。對(duì)于初學(xué)者來(lái)說(shuō),理解和記住這么多的內(nèi)容可能是一個(gè)挑戰(zhàn)。
算子之間的組合應(yīng)用:很多情況下,單獨(dú)使用一個(gè)算子并不能完成復(fù)雜的任務(wù),而是需要多個(gè)算子相互配合。這就要求學(xué)習(xí)者不僅要了解各個(gè)算子的工作原理,還要懂得如何將它們有機(jī)地結(jié)合起來(lái),以實(shí)現(xiàn)更復(fù)雜的功能。
參數(shù)調(diào)優(yōu):每個(gè)算子通常都帶有一系列可調(diào)節(jié)的參數(shù),這些參數(shù)的選擇直接影響到最終的結(jié)果。找到一組最優(yōu)化的參數(shù)值往往需要通過(guò)不斷的實(shí)驗(yàn)和嘗試,這既考驗(yàn)?zāi)托囊部简?yàn)經(jīng)驗(yàn)。
解決實(shí)際問(wèn)題的能力:將理論知識(shí)應(yīng)用于實(shí)踐,解決真實(shí)世界中的問(wèn)題是學(xué)習(xí)任何技術(shù)的關(guān)鍵。對(duì)于OpenCV而言,這意味著要能夠分析給定的任務(wù)需求,確定所需的操作步驟,并正確地執(zhí)行這些步驟。為了克服上述困難,建議多做練習(xí),特別是針對(duì)不同類型的圖像處理任務(wù)進(jìn)行實(shí)戰(zhàn)演練。同時(shí),可以參考官方文檔、在線教程以及社區(qū)討論來(lái)加深對(duì)算子的理解,學(xué)習(xí)他人是如何解決問(wèn)題的。此外,不斷積累經(jīng)驗(yàn)和案例研究也會(huì)有助于提高解決新問(wèn)題的能力。
本文章主要講述如何在邊緣端設(shè)備上使用OpenCV。本次使用的邊緣端設(shè)備是凌智電子開(kāi)發(fā)的凌智視覺(jué)模塊,具體如下:
如對(duì)該邊緣端設(shè)備感興趣,可到Gitee倉(cāng)庫(kù):凌智視覺(jué)模塊查看該設(shè)備的具體信息。
接下來(lái)我們通過(guò)幾個(gè)例子來(lái)介紹如何在邊緣端設(shè)備使用OpenCV進(jìn)行形狀檢測(cè)。
3.1 矩形檢測(cè)
importlockzhiner_vision_module.cv2ascv2fromlockzhiner_vision_module.editimportEditimporttimeimportsysif__name__ =="__main__": args = sys.argv iflen(args) !=3: print("Need model path. Example: python test_capture.py width height") exit(1) edit = Edit() edit.start_and_accept_connection() video_capture = cv2.VideoCapture() video_capture.set_width(int(args[1])) video_capture.set_height(int(args[2])) ifvideo_capture.open(0)isFalse: print("Failed to open capture") exit(1) whileTrue: read_index =0 total_time_ms =0 foriinrange(30): start_time = time.time() ret, mat = video_capture.read() ifretisFalse: continue end_time = time.time() # 轉(zhuǎn)換為灰度圖像 gray = cv2.cvtColor(mat, cv2.COLOR_BGR2GRAY) # 高斯模糊 blurred = cv2.GaussianBlur(gray, (5, 5), 0) # 二值化 _, binary = cv2.threshold(blurred, 127, 255, cv2.THRESH_BINARY_INV) edges = cv2.Canny(binary, 30, 200) contours, _ = cv2.findContours(edges.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) for contour in contours: # 近似輪廓 # 計(jì)算輪廓周長(zhǎng) epsilon = 0.02 * cv2.arcLength(contour, True) # 將輪廓近似為多邊形 if epsilon < 15:? ? ? ? ? ? ? ? ? ? continue? ? ? ? ? ? ? ? approx = cv2.approxPolyDP(contour, epsilon, True)? ? ? ? ? ? ? ? # 如果近似輪廓有4個(gè)頂點(diǎn),則認(rèn)為是矩形? ? ? ? ? ? ? ? if len(approx) == 4:? ? ? ? ? ? ? ? ? ? cv2.putText(mat, "Rectangle", (50,50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)? ? ? ? ? ? ? ? ? ? cv2.drawContours(mat, [approx], -1, (0, 255, 0), 2)? ? ? ? ? ? edit.print(mat)? ? ? ? ? ? total_time_ms += end_time - start_time? ? ? ? ? ? read_index += 1? ? ? ? print(f"FPS is {1.0 / (total_time_ms / read_index)}")
在這一段代碼中的檢測(cè)效果如下圖所示
但是當(dāng)我們只想要外部的矩形時(shí),我們可以怎么做呢?
contours, _ = cv2.findContours(edges.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
效果如上圖所示,接下來(lái)我們就得深究一下cv2.findContours mode 參數(shù) 和 method 參數(shù)的區(qū)別及作用了,我就不一一演示了,大家伙可以自行實(shí)驗(yàn),畢竟我也踩過(guò)。mode: 輪廓檢索模式,定義了如何檢索輪廓及其層次結(jié)構(gòu)。有以下幾種選擇:
cv2.RETR_EXTERNAL: 只檢索最外層的輪廓。
cv2.RETR_LIST: 檢索所有的輪廓,但不建立它們之間的等級(jí)關(guān)系。
cv2.RETR_CCOMP: 檢索所有的輪廓,并將它們組織為兩級(jí)層次結(jié)構(gòu):頂層是外部邊界,次級(jí)是孔洞。
cv2.RETR_TREE: 檢索所有輪廓,并重建完整的包含關(guān)系。
method: 輪廓近似方法,決定了輪廓的精度。有以下幾種選擇:
cv2.CHAIN_APPROX_NONE: 存儲(chǔ)所有的輪廓點(diǎn),即沒(méi)有近似。
cv2.CHAIN_APPROX_SIMPLE: 壓縮水平、垂直和對(duì)角方向上的元素,只保留端點(diǎn)。
cv2.CHAIN_APPROX_TC89_L1: 使用一種稱為 Teh-Chin 鏈逼近算法的更復(fù)雜的壓縮方式。
cv2.CHAIN_APPROX_TC89_KCOS: 同樣使用 Teh-Chin 鏈逼近算法,但與 L1 不同,它是基于 KCOS 的。
3.2 圓形檢測(cè)
OpenCV 提供了HoughCircles函數(shù)來(lái)檢測(cè)圓形。Hough變換是一種用于從圖像中提取幾何形狀(如直線、圓等)的技術(shù),它通過(guò)參數(shù)空間的投票機(jī)制來(lái)實(shí)現(xiàn)。對(duì)于圓形檢測(cè),Hough變換可以識(shí)別出滿足特定條件的圓形結(jié)構(gòu)。下面是使用 OpenCV 進(jìn)行圓形檢測(cè)的基本步驟:
首先加載需要檢測(cè)圓的圖像,并將其轉(zhuǎn)換為灰度圖,因?yàn)轭伾畔?duì)于圓形檢測(cè)不是必要的。調(diào)用cv2.HoughCircles函數(shù)進(jìn)行圓形檢測(cè)。該函數(shù)接受幾個(gè)重要參數(shù):
method:定義了檢測(cè)方法,通常使用cv2.HOUGH_GRADIENT。
dp:累加器分辨率與圖像分辨率的反比。dp=1 表示累加器具有與輸入圖像相同的分辨率。
minDist:檢測(cè)到的圓心之間的最小距離。如果設(shè)置得太小,可能會(huì)檢測(cè)到多個(gè)相鄰的圓;如果太大,可能會(huì)漏檢一些圓。
param1:Canny邊緣檢測(cè)的高閾值,低閾值是高閾值的一半。
param2:累加器閾值。該閾值越小,檢測(cè)到的圓越多(包括不完美的圓)。越大則只檢測(cè)到更明顯的圓。
minRadius和maxRadius:分別為檢測(cè)到的圓的最小和最大半徑。
請(qǐng)注意,上述參數(shù) (dp,minDist,param1,param2,minRadius,maxRadius) 需要根據(jù)具體應(yīng)用場(chǎng)景調(diào)整,以獲得最佳檢測(cè)效果。例如,不同的光照條件、背景復(fù)雜度或者目標(biāo)圓的大小都會(huì)影響這些參數(shù)的選擇。實(shí)例代碼
fromlockzhiner_vision_module.cv2importVideoCaptureimportlockzhiner_vision_module.cv2ascv2fromlockzhiner_vision_module.editimportEditimporttimeimportsyspi =3.14159265358979323846if__name__ =="__main__": args = sys.argv iflen(args) !=3: print("Need model path. Example: python test_capture.py width height") exit(1) edit = Edit() edit.start_and_accept_connection() video_capture = VideoCapture() video_capture.set_width(int(args[1])) video_capture.set_height(int(args[2])) ifvideo_capture.open(0)isFalse: print("Failed to open capture") exit(1) whileTrue: read_index =0 total_time_ms =0 foriinrange(30): start_time = time.time() ret, mat = video_capture.read() ifretisFalse: continue end_time = time.time() # 轉(zhuǎn)換為灰度圖像 # 轉(zhuǎn)換為灰度圖像 gray = cv2.cvtColor(mat, cv2.COLOR_BGR2GRAY) # 使用高斯模糊減少噪聲 blurred = cv2.GaussianBlur(gray, (9, 9), 2) # 使用 HoughCircles 檢測(cè)圓形 circles = cv2.HoughCircles(blurred, cv2.HOUGH_GRADIENT, dp=1, minDist=50, param1=50, param2=30, minRadius=120, maxRadius=250) # print(circles) if circles is not None: # 在圖像上繪制檢測(cè)到的圓 for i in circles[0]: center = (int(i[0]), int(i[1])) radius = int(i[2]) cv2.putText(mat, "circle", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2) # 繪制圓心 cv2.circle(mat, center, 1, (0, 100, 100), 3) # 繪制圓 cv2.circle(mat, center, radius, (0, 255, 0), 3) edit.print(mat) total_time_ms += end_time - start_time read_index += 1 print(f"FPS is {1.0 / (total_time_ms/read_index)}")
檢測(cè)效果圖 :
-
圖像處理
+關(guān)注
關(guān)注
27文章
1300瀏覽量
56887 -
AI
+關(guān)注
關(guān)注
87文章
31507瀏覽量
270302 -
OpenCV
+關(guān)注
關(guān)注
31文章
635瀏覽量
41552
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論