【人工智能學習之圖像操作(六)】
- Hough變換
- 直線檢測
- 圓檢測
- 圖像分割
Hough變換
在圖像處理中,霍夫變換用來檢測任意能夠用數學公式表達的形狀,即使這個形狀被破壞或者有點扭曲
直線檢測
import cv2
import numpy as np
image = cv2.imread("1.jpg")
image = cv2.GaussianBlur(image, (5, 5), 50)
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imshow("image_gray", image_gray)
edges = cv2.Canny(image_gray, 100, 150)
cv2.imshow("image_edges", edges)
lines = cv2.HoughLines(edges, 1, np.pi / 180, 100)
for line in lines:
rho, theta = line[0]
a = np.cos(theta)
b = np.sin(theta)
x0 = a * rho
y0 = b * rho
x1 = int(x0 + 1000 * (-b)) # 直線起點橫坐標
y1 = int(y0 + 1000 * (a)) # 直線起點縱坐標
x2 = int(x0 - 1000 * (-b)) # 直線終點橫坐標
y2 = int(y0 - 1000 * (a)) # 直線終點縱坐標
cv2.line(image, (x1, y1), (x2, y2), (0, 0, 255), 2)
cv2.imshow("image_lines", image)
cv2.waitKey(0)
圓檢測
import cv2
import numpy as np
image = cv2.imread("2.jpg")
dst = cv2.cvtColor(image, cv2.COLOR_BGRA2GRAY)
circle = cv2.HoughCircles(dst, cv2.HOUGH_GRADIENT, 1, 30, param1=40, param2=20,
minRadius=20, maxRadius=300)
if not circle is None:
circle = np.uint16(np.around(circle))
for i in circle[0, :]:
cv2.circle(image, (i[0], i[1]), i[2], (0, 255, 0), 2)
cv2.imshow("circle", image)
cv2.waitKey(0)
原理詳解
步驟:
- 輪廓檢測算法檢測出輪廓
- 投射到hough空間進行形狀檢測
數學原理
圖像分割
函數:cv2.watershed()
- 原理:
任何一副灰度圖像都可以被看成拓撲平面,灰度值高的區域可以被看成是山峰,灰度值低的區域可以被看成是山谷。我們向每一個山谷中灌不同顏色的水。隨著水的位的升高,不同山谷的水就會相遇匯合,為了防止不同山谷的水匯合,我們需要在水匯合的地方構建起堤壩。不停的灌水,不停的構建堤壩知道所有的山峰都被水淹沒。我們構建好的堤壩就是對圖像的分割。這就是分水嶺算法的背后哲理。
但是這種方法通常都會得到過度分割的結果,這是由噪聲或者圖像中其他不規律的因素造成的。為了減少這種影響,OpenCV 采用了基于掩模的分水嶺算法,在這種算法中我們要設置那些山谷點會匯合,那些不會。這是一種交互式的圖像分割。我們要做的就是給我們已知的對象打上不同的標簽。如果某個區域肯定是前景或對象,就使用某個顏色(或灰度值)標簽標記它。如果某個區域肯定不是對象而是背景就使用另外一個顏色標簽標記。而剩下的不能確定是前景還是背景的區域就用 0 標記。這就是我們的標簽。然后實施分水嶺算法。每一次灌水,我們的標簽就會被更新,當兩個不同顏色的標簽相遇時就構建堤壩,直到將所有山峰淹沒,最后我們得到的邊界對象(堤壩)的值為 -1。 - 代碼示例
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('1.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV |
cv2.THRESH_OTSU)
# noise removal
kernel = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
# sure background area
sure_bg = cv2.dilate(opening, kernel, iterations=3)
dist_transform = cv2.distanceTransform(opening, 1, 5)
ret, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)
# Finding unknown region
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)
# Marker labelling
ret, markers1 = cv2.connectedComponents(sure_fg)
# Add one to all labels so that sure background is not 0, but 1
markers = markers1 + 1
# Now, mark the region of unknown with zero
markers[unknown == 255] = 0
markers3 = cv2.watershed(img, markers)
img[markers3 == -1] = [255, 0, 0]
cv2.imshow("img", img)
cv2.waitKey(0)