使用Python,OpenCV進行基本的影像處理——提取紅色圓圈輪廓并繪制
- 1. 效果圖
- 2. 原始碼
寫這篇博客源于博友的提問,想提取圖片中的紅色圓圈坐標,并繪制封閉的輪廓,

看到這個首先有幾個解決思路:
1. 霍夫圓提取
2. 圓圈均是紅色,可以轉換HSV色彩空間提取
3. 應用一系列影像處理:灰度圖、形態學操作、閾值化進行簡單提取
一個一個嘗試,霍夫圓不是很理想,調整了引數,也沒有全部提取到,只提取到了部分,
HSV色彩空間提取紅色,因為對紅色的HSV范圍設定的不夠合理,效果也不是很好,
還是使用一系列影像處理,得到了比較理想的結果,
1. 效果圖
檢測原始圖 VS 效果圖如下:
可以看到右圖中,輪廓被用閉合的綠色輪廓連接起來,

檢測程序1——原圖 VS 剪裁后圖如下:
- 裁剪后圖:忽略邊界坐標軸對輪廓提取的影響;

檢測程序2—— 灰度圖 VS 白帽圖 VS 梯度圖 VS 形態學閉合圖如下:
- 灰度圖:忽略色彩影響;
- 白帽圖:從較暗的背景中提取較亮的區域
- 梯度圖:計算Schaar梯度圖,使用梯度來檢測影像中的邊緣,更好的在影像中找到物件的輪廓和邊緣線;
- 形態學閉合圖:矩形框形態學閉合操作,以幫助閉合輪廓間小的縫隙

檢測程序3——形態學閉合圖 VS 二值化圖1 VS 閾值化圖2 如下:
- 二值化圖:使得影像以白色前景和黑色背景呈現,以便于輪廓提取
- 閾值化圖:方形框形態學閉合操作,以二次幫助閉合小的縫隙

識別程序3——輪廓過濾圖 VS 提取最終效果圖 如下:
輪廓過濾圖:根據面積只保留夠大的輪廓圖(截取完的圖片只包含倆個輪廓,無需過濾,用原始圖則需要過濾)
最終效果圖:倆個大的輪廓被成功提取
繪制檢測到的輪廓的組成點為藍色空心圓形,繪制輪廓為綠色矩形,

檢測結果——裁剪后圖檢測效果圖 VS 原圖直接檢測效果圖對比:
可以看到當直接使用原圖進行上述檢測,坐標軸邊界會有干擾,結果中會檢測出多余的輪廓,

2. 原始碼
# 提取圓圈的輪廓,并繪制
import cv2
import imutils
import numpy as np
# 初始化矩形和方形結構內核
# 在影像上滑動它來進行(卷積)操作,如模糊、銳化、邊緣檢測或其他影像處理操作,
# 使用矩形函式作為Top-hat形態學運算子,使用方形函式作為閉合運算,
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
# 加載輸入影像,轉換為灰度圖
origin = cv2.imread('images/circle.png')
image = origin.copy()
width = 75
height = 34
# # 只截取有輪廓的區域,避免坐標軸線等干擾
image = image[height:369, width:512]
cv2.imshow("origin", origin)
cv2.imshow("crop", image)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imshow("gray", gray)
# 執行形態學操作
# 應用tophat(白帽)形態學操作以在暗的背景中提取出亮的區域
# Top hat操作在深色背景(即信用卡號)下顯示淺色區域
tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel)
cv2.imshow("tophat", tophat)
# 計算Scharr梯度,計算梯度值
# 在白色禮帽上,計算x方向的Scharr梯度,然后縮放到范圍[0, 255]
gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1)
gradX = np.absolute(gradX)
(minVal, maxVal) = (np.min(gradX), np.max(gradX))
# 最小/最大歸一化, 由float轉換gradX到uint8范圍[0-255]
gradX = (255 * ((gradX - minVal) / (maxVal - minVal)))
gradX = gradX.astype("uint8")
cv2.imshow("gradient", gradX)
# 使用矩形框應用閉合操作以幫助閉合信用卡數字之間的小的縫隙
# 應用Otsu's閾值方法二值化影像
gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)
cv2.imshow("morphologyEx", gradX)
thresh = cv2.threshold(gradX, 0, 255,
cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv2.imshow("thresh1", thresh)
# 在二值化影像上,應用二次閉合操作
# 再一次方形框形態學操作,幫助閉合小的的縫隙
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel)
cv2.imshow("thresh2", thresh)
# 閾值影像中查找輪廓,然后初始化數字位置串列
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
print(len(cnts))
img = image.copy()
# 遍歷輪廓
for (i, c) in enumerate(cnts):
area = cv2.contourArea(c)
print(i, area)
# 根據面積過濾掉不符合的輪廓
if (area < 4000):
continue
# print(' c: ', type(c), c.shape, c[0], type([c]))
cc = c.copy()
cc[:, :, 0] += width
cc[:, :, 1] += height
# print('cc: ', type(cc), cc.shape, cc[0])
for coor in c:
# 在輪廓的每個小圓上繪制藍色圓圈
cv2.circle(img, (coor[0][0],coor[0][1]),5, (255, 0, 0), 1)
cv2.drawContours(origin, [cc], -1, (0, 255, 0), 2)
cv2.drawContours(image, [c], -1, (0, 255, 0), 2)
cv2.imshow("origin res", origin)
cv2.imshow("img res", img)
cv2.imshow("image res", image)
cv2.imwrite("images/crop_circle_extract.jpg",image)
cv2.waitKey(0)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/296790.html
標籤:其他
上一篇:女朋友嫌我拍的照片有霧,連夜用OpenCV寫出??去霧演算法??逃過一劫(收藏保命)
下一篇:DNS欺騙原理
