1 簡介
Opencv(Open Source Computer Vision Library)是一個基于開源發行的跨平臺計算機視覺庫,它實現了圖像處理和計算機視覺方面的很多通用算法,已成為計算機視覺領域最有力的研究工具。在深度學習中,我們會經常接觸到兩個名稱,圖像處理和計算機視覺,它們之間有什么區別呢?圖像處理 (Image Processing)
目的:圖像處理主要集中在改善或轉換圖像的質量,使得圖像更適合人類觀察或者為后續的分析做準備。
方法:通常涉及像素級別的操作,比如調整亮度、對比度、顏色校正、濾波(如高斯模糊、中值濾波去噪)、邊緣檢測、形態學變換(膨脹、腐蝕)等。
計算機視覺 (Computer Vision)
目的:計算機視覺的目標是使計算機能夠理解和解釋圖像或視頻的內容,實現類似于人類視覺系統的感知能力。
方法:使用高級算法來解析圖像中的內容,包括但不限于特征提取、物體識別、分類、跟蹤、場景重建等。這可能涉及到機器學習和深度學習模型的應用。
簡而言之,圖像處理是計算機視覺的基礎,提供了必要的工具和技術來預處理和優化圖像數據;而計算機視覺則是在此基礎之上,通過更加復雜的算法和模型來解析圖像的意義。在實際應用中,這兩者往往是緊密結合的,共同作用于解決復雜的問題。例如,在一個自動駕駛系統中,圖像處理可能會用于清理傳感器輸入的數據,而計算機視覺則負責識別道路上的行人、車輛和其他重要元素。
2 基礎知識
OpenCV 是一個開源的計算機視覺和機器學習軟件庫,廣泛用于圖像處理、視頻捕捉、物體檢測等領域。一些常用操作及其目的:
讀取圖片
使用cv2.imread()函數加載圖像。
目的:為后續處理和分析準備圖像數據。
轉換色彩空間
使用cv2.cvtColor()進行色彩空間轉換。
目的:適應不同算法的需求,例如灰度圖用于簡化計算,HSV用于顏色分割等。
濾波
高斯模糊 (cv2.GaussianBlur)、均值濾波 (cv2.blur) 和雙邊濾波 (cv2.bilateralFilter) 等。
目的:降噪和平滑圖像,或在保持邊緣的同時模糊細節。
繪制圖形
使用cv2.line()、cv2.rectangle()、cv2.circle()和cv2.polylines()來繪制直線、矩形、圓形或多邊形。
目的:可視化結果,標注圖像中的特征或者創建掩碼。
邊緣檢測
Canny 邊緣檢測 (cv2.Canny) 或 Sobel 操作符 (cv2.Sobel)。
目的:檢測圖像中物體的邊界,是很多高級計算機視覺任務的基礎步驟。
閾值操作
cv2.threshold()用于二值化圖像。
目的:突出顯示感興趣區域,簡化圖像以利于進一步分析。
Sobel 濾波
使用cv2.Sobel()計算圖像梯度。
目的:增強邊緣,通常與邊緣檢測相關聯。
文件保存
cv2.imwrite()將圖像保存到磁盤。
目的:保存處理后的圖像以便將來使用或分享。
此外,還有其他重要的OpenCV功能,如:
直方圖均衡化(cv2.equalizeHist) 提升圖像對比度。
模板匹配(cv2.matchTemplate) 用于查找一個圖像中的另一個小圖像的位置。
特征點檢測和描述子計算,如 SIFT, SURF, ORB 等,用于圖像配準、拼接等任務。
這些基礎操作和高級特性共同構成了強大的工具集,可以用來開發從簡單的圖像編輯應用到復雜的計算機視覺系統。 這些操作是構建復雜圖像處理流水線的基礎,可以單獨使用,也可以組合起來解決更復雜的視覺問題。例如,預處理階段可能會包括去噪、邊緣檢測和形態學操作;而在后處理階段,則可能會涉及閾值操作和繪制幾何圖形來標注或解釋結果。以上這些算子僅僅是OpenCV庫的一小部分的內容,但是它們是支持我們進行復雜操作的基礎。
3 實際操作
在學習OpenCV的初期,可能會覺得每個算子或函數就像是獨立的知識點,雖然能夠理解它們各自的功能和用法,但當面對實際問題時,卻難以將這些知識點有效地組合起來解決問題。這是因為從理論到實踐的應用需要一個過渡的過程,在這個過程中,不僅需要掌握單個算子的操作,還需要學會如何根據具體的需求選擇合適的算子,并且合理地調整參數以達到預期的效果。OpenCV的強大之處在于它提供了豐富的圖像處理功能,但這也意味著使用它的難點在于:
理解和記憶大量的算子:OpenCV庫中包含了大量的算子,每個算子都有其特定的應用場景和參數設置。對于初學者來說,理解和記住這么多的內容可能是一個挑戰。
算子之間的組合應用:很多情況下,單獨使用一個算子并不能完成復雜的任務,而是需要多個算子相互配合。這就要求學習者不僅要了解各個算子的工作原理,還要懂得如何將它們有機地結合起來,以實現更復雜的功能。
參數調優:每個算子通常都帶有一系列可調節的參數,這些參數的選擇直接影響到最終的結果。找到一組最優化的參數值往往需要通過不斷的實驗和嘗試,這既考驗耐心也考驗經驗。
解決實際問題的能力:將理論知識應用于實踐,解決真實世界中的問題是學習任何技術的關鍵。對于OpenCV而言,這意味著要能夠分析給定的任務需求,確定所需的操作步驟,并正確地執行這些步驟。為了克服上述困難,建議多做練習,特別是針對不同類型的圖像處理任務進行實戰演練。同時,可以參考官方文檔、在線教程以及社區討論來加深對算子的理解,學習他人是如何解決問題的。此外,不斷積累經驗和案例研究也會有助于提高解決新問題的能力。
本文章主要講述如何在邊緣端設備上使用OpenCV。本次使用的邊緣端設備是凌智電子開發的凌智視覺模塊,具體如下:
如對該邊緣端設備感興趣,可到Gitee倉庫:凌智視覺模塊查看該設備的具體信息。
接下來我們通過幾個例子來介紹如何在邊緣端設備使用OpenCV進行形狀檢測。
3.1 矩形檢測
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() # 轉換為灰度圖像 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: # 近似輪廓 # 計算輪廓周長 epsilon = 0.02 * cv2.arcLength(contour, True) # 將輪廓近似為多邊形 if epsilon < 15:? ? ? ? ? ? ? ? ? ? continue? ? ? ? ? ? ? ? approx = cv2.approxPolyDP(contour, epsilon, True)? ? ? ? ? ? ? ? # 如果近似輪廓有4個頂點,則認為是矩形? ? ? ? ? ? ? ? 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)}")
在這一段代碼中的檢測效果如下圖所示
但是當我們只想要外部的矩形時,我們可以怎么做呢?
contours, _ = cv2.findContours(edges.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
效果如上圖所示,接下來我們就得深究一下cv2.findContours mode 參數 和 method 參數的區別及作用了,我就不一一演示了,大家伙可以自行實驗,畢竟我也踩過。mode: 輪廓檢索模式,定義了如何檢索輪廓及其層次結構。有以下幾種選擇:
cv2.RETR_EXTERNAL: 只檢索最外層的輪廓。
cv2.RETR_LIST: 檢索所有的輪廓,但不建立它們之間的等級關系。
cv2.RETR_CCOMP: 檢索所有的輪廓,并將它們組織為兩級層次結構:頂層是外部邊界,次級是孔洞。
cv2.RETR_TREE: 檢索所有輪廓,并重建完整的包含關系。
method: 輪廓近似方法,決定了輪廓的精度。有以下幾種選擇:
cv2.CHAIN_APPROX_NONE: 存儲所有的輪廓點,即沒有近似。
cv2.CHAIN_APPROX_SIMPLE: 壓縮水平、垂直和對角方向上的元素,只保留端點。
cv2.CHAIN_APPROX_TC89_L1: 使用一種稱為 Teh-Chin 鏈逼近算法的更復雜的壓縮方式。
cv2.CHAIN_APPROX_TC89_KCOS: 同樣使用 Teh-Chin 鏈逼近算法,但與 L1 不同,它是基于 KCOS 的。
3.2 圓形檢測
OpenCV 提供了HoughCircles函數來檢測圓形。Hough變換是一種用于從圖像中提取幾何形狀(如直線、圓等)的技術,它通過參數空間的投票機制來實現。對于圓形檢測,Hough變換可以識別出滿足特定條件的圓形結構。下面是使用 OpenCV 進行圓形檢測的基本步驟:
首先加載需要檢測圓的圖像,并將其轉換為灰度圖,因為顏色信息對于圓形檢測不是必要的。調用cv2.HoughCircles函數進行圓形檢測。該函數接受幾個重要參數:
method:定義了檢測方法,通常使用cv2.HOUGH_GRADIENT。
dp:累加器分辨率與圖像分辨率的反比。dp=1 表示累加器具有與輸入圖像相同的分辨率。
minDist:檢測到的圓心之間的最小距離。如果設置得太小,可能會檢測到多個相鄰的圓;如果太大,可能會漏檢一些圓。
param1:Canny邊緣檢測的高閾值,低閾值是高閾值的一半。
param2:累加器閾值。該閾值越小,檢測到的圓越多(包括不完美的圓)。越大則只檢測到更明顯的圓。
minRadius和maxRadius:分別為檢測到的圓的最小和最大半徑。
請注意,上述參數 (dp,minDist,param1,param2,minRadius,maxRadius) 需要根據具體應用場景調整,以獲得最佳檢測效果。例如,不同的光照條件、背景復雜度或者目標圓的大小都會影響這些參數的選擇。實例代碼
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() # 轉換為灰度圖像 # 轉換為灰度圖像 gray = cv2.cvtColor(mat, cv2.COLOR_BGR2GRAY) # 使用高斯模糊減少噪聲 blurred = cv2.GaussianBlur(gray, (9, 9), 2) # 使用 HoughCircles 檢測圓形 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: # 在圖像上繪制檢測到的圓 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)}")
檢測效果圖 :
-
圖像處理
+關注
關注
27文章
1289瀏覽量
56722 -
AI
+關注
關注
87文章
30728瀏覽量
268886 -
OpenCV
+關注
關注
31文章
634瀏覽量
41337
發布評論請先 登錄
相關推薦
評論