21直线检测
霍夫直线变换用来做直线检测,前提条件是边缘检测已完成。
import cv2 as cv
import numpy as np
def line_detection(image):
gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray,50,150,apertureSize=3)
lines = cv.HoughLines(edges, 1, np.pi/180, 200)
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))
cv.line(image,(x1,y1),(x2,y2),(0,0,255),2)
cv.imshow("image_line", image)
def line_detect_possible_demo(image):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray, 50, 150, apertureSize=3)
lines = cv.HoughLinesP(edges, 1, np.pi / 180, 100, minLineLength=50,maxLineGap=10)
for line in lines:
x1,y1,x2,y2 = line[0]
cv.line(image,(x1,y1),(x2,y2),(0,0,255),2)
cv.imshow("line_detect_possible_demo", image)
22圆检测
霍夫圆变换原理:
- 从平面坐标到极坐标转换,三个参数C(x0,y0,r),其中x0y0是圆心
- 假设平面坐标上任意一个圆上的点转换到极坐标中C(x0,y0,r)处有最大值,霍夫变换正是利用这一原理来检测圆的。
现实考量:
- 霍夫检测噪声敏感,所以首先对图像做中值滤波。
- 基于效率考虑,分为两步:
检测边缘,发现可能的圆心。
基于上一步,从候选圆心开始计算最佳半径大小。
import cv2 as cv
import numpy as np
def Hough_Circle_demo(image):
dst = cv.pyrMeanShiftFiltering(image, 10, 100)
cimage = cv.cvtColor(dst, cv.COLOR_BGR2GRAY)
circles = cv.HoughCircles(cimage, cv.HOUGH_GRADIENT, 1, 20,param1=50, param2=20, minRadius=0, maxRadius=0)
circles = np.uint16(np.around(circles))
for i in circles[0, :]:
cv.circle(image, (i[0], i[1]), i[2], (0, 255, 0), 2)
cv.circle(image, (i[0], i[1]), 2, (0, 0, 255), 3)
cv.imshow("circles",image)
print("=====Hello Python=====")
image = cv.imread("opencv_sources/circle.png")
cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)
cv.imshow("input image",image)
Hough_Circle_demo(image)
cv.waitKey(0)
cv.destroyAllWindows()
23轮廓发现
是基于图像边缘提取的基础寻找对象轮廓的方法。
import cv2 as cv
def contours_demo(image):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
cv.imshow("binary image",binary)
cloneImage, contours, heriachy = cv.findContours(binary, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
for i , contour in enumerate(contours):
cv.drawContours(image, contours, i, (0,0,255), 2)
print(i)
cv.imshow("detect contours",image)
print("=====Hello Python=====")
image = cv.imread("opencv_sources/circle.png")
cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)
cv.imshow("input image",image)
contours_demo(image)
cv.waitKey(0)
cv.destroyAllWindows()
canny轮廓提取的效果
import cv2 as cv
import numpy as np
def edge_demo(image):
blured = cv.GaussianBlur(image, (3, 3), 0) # 高斯模糊降低噪声
gray = cv.cvtColor(blured, cv.COLOR_BGR2GRAY)
# x gradient
xgrad = cv.Sobel(gray, cv.CV_16SC1, 1, 0)
# y gradient
ygrad = cv.Sobel(gray, cv.CV_16SC1, 0, 1)
# edge
edge_output = cv.Canny(xgrad, ygrad, 50, 150) # 低阈值50高阈值150
return edge_output
def contours_demo(image):
binary = edge_demo(image)
cloneImage, contours, heriachy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
for i , contour in enumerate(contours):
cv.drawContours(image, contours, i, (0,0,255), 1)
print(i)
cv.imshow("detect contours",image)
print("=====Hello Python=====")
image = cv.imread("opencv_sources/circle.png")
cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)
cv.imshow("input image",image)
contours_demo(image)
cv.waitKey(0)
cv.destroyAllWindows()
24对象测量
- 弧长与面积:轮廓发现,计算每个轮廓的弧长与面积,像素单位。
- 多边形拟合:获取轮廓的多边形拟合结果。
- 几何矩计算:使用几何矩计算对象中心。
import cv2 as cv
import numpy as np
def measure_object(image):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)
print("threshold value:%s"%ret)
cv.imshow("binary image",binary)
outImage, contours, hireachy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
for i, contour in enumerate(contours):
area = cv.contourArea(contour)
x,y,w,h = cv.boundingRect(contour)
mm = cv.moments(contour) # 几何矩,字典类型
if mm['m00']:
cx = mm['m10']/mm['m00']
cy = mm['m01']/mm['m00']
else:
continue
cv.circle(image, (np.int(cx),np.int(cy)), 3, (0,255,255), -1)
cv.rectangle(image, (x,y), (x+w,y+h), (0,0,255), 2)
print("contour area %s"%area)
cv.imshow("measure-contours", image)
print("=====Hello Python=====")
image = cv.imread("opencv_sources/rect.png")
cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)
cv.imshow("input image",image)
measure_object(image)
cv.waitKey(0)
cv.destroyAllWindows()
多边形拟合
import cv2 as cv
import numpy as np
def measure_object(image):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
print("threshold value:%s"%ret)
cv.imshow("binary image",binary)
dst = cv.cvtColor(binary, cv.COLOR_GRAY2BGR)
outImage, contours, hireachy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
for i, contour in enumerate(contours):
area = cv.contourArea(contour)
x,y,w,h = cv.boundingRect(contour)
# 求宽高比
rate = min(w, h)/max(w, h)
print("rectangle rate:%s"%rate)
mm = cv.moments(contour) # 几何矩,字典类型
type(mm)
if mm['m00']:
cx = mm['m10']/mm['m00']
cy = mm['m01']/mm['m00']
else:
continue
cv.circle(dst, (np.int(cx),np.int(cy)), 3, (0,255,255), -1)
# cv.rectangle(dst, (x,y), (x+w,y+h), (0,0,255), 2)
print("contour area %s"%area)
# 多边形逼近
approxCurve = cv.approxPolyDP(contour, 4 , True)
if approxCurve.shape[0] == 3: # 多边形的边数
cv.drawContours(dst, contours, i, (0,255,0), 2)
cv.imshow("measure-contours", dst)
print("=====Hello Python=====")
image = cv.imread("opencv_sources/approxi.png")
cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)
cv.imshow("input image",image)
measure_object(image)
cv.waitKey(0)
cv.destroyAllWindows()
25膨胀与腐蚀
膨胀的作用:对象增加一个像素;平滑对象边缘;减少或填充对象之间的距离
import cv2 as cv
def erode_demo(image):
gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
kernel = cv.getStructuringElement(cv.MORPH_RECT,(3,3))
dst = cv.erode(binary, kernel)
cv.imshow("erode_demo",dst)
def dilate_demo(image):
gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
kernel = cv.getStructuringElement(cv.MORPH_RECT,(5,5))
dst = cv.dilate(binary, kernel)
cv.imshow("dilate_demo",dst)
print("=====Hello Python=====")
image = cv.imread("opencv_sources/rect.png")
cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)
cv.imshow("input image",image)
dilate_demo(image)
cv.waitKey(0)
cv.destroyAllWindows()
网友评论