效果图:
可见识别结果是正确的
先说思路,稍后会在文章后边附上源码。。
1.首先通过cv2.imread()导入图片
2.进行高斯模糊,滤除噪声干扰
3.运用Canny识别边缘
4.运用ROI掩膜,将无关部分除去
5(核心).霍夫变换,通过调节参数改良线段识别结果
6.进行线段交点的运算,因为霍夫变换往往不止识别一条线段,所以会有大量误差点的存在
7.运用集合set进行第一步去重
8.将去重结果,根据点之间的距离设置阈值,进行二次去重
8.绘制,输出图像
代码如下:)
import cv2
import numpy as np
#Gauss
def gaussian_blur(img,kernal_size=3):
gray_img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #to gray
result_img=cv2.GaussianBlur(gray_img,(kernal_size,kernal_size),1)
return result_img
#Canny
def canny_filter(img,th1=50,th2=150):
result_img=cv2.Canny(img,th1,th2)
return result_img
#roi
def roi_mask(img):
points=np.array([[(303,48),(589,229),(335,650),(31,401)]])
mask=np.zeros_like(img) #mask
cv2.fillPoly(mask,points,255)
result_img=cv2.bitwise_and(img,mask) #main bitwise
return result_img
def hough_lines(img):
#Hough rusult
result_img=np.zeros((img.shape[0],img.shape[1]),dtype=np.uint8)
rho=1
theta=np.pi/180
threshold=15
min_line_len=120
max_line_gap=20
lines = cv2.HoughLinesP(img,rho,theta,threshold,minLineLength=min_line_len,maxLineGap=max_line_gap)
#print(lines)
for line in lines:
for x1,y1,x2,y2 in line:
cv2.line(result_img,(x1,y1),(x2,y2),[255,255,255],1)
return result_img,lines
def intersection_point(x1, y1, x2, y2, x3, y3, x4, y4): #输入四条直线坐标,返回交点
A1 = y2 - y1
B1 = x1 - x2
C1 = A1 * x1 + B1 * y1
A2 = y4 - y3
B2 = x3 - x4
C2 = A2 * x3 + B2 * y3
denominator = A1 * B2 - A2 * B1
if denominator == 0:
return None # The lines are parallel.
x = (B2 * C1 - B1 * C2) / denominator
y = (A1 * C2 - A2 * C1) / denominator
return (x, y)
type1=[]
type2=[]
my_count=[]
my_set=[]
def distance(p1, p2):
"""计算两点之间的距离"""
return int(((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2) ** 0.5)
def remove_close_points(myset_list, threshold):
"""
根据距离阈值去除接近的点,只保留一个。
这里采用简单的方法:对于每个点,检查它是否与其他已保留的点足够远。
"""
kept_points = []
for p in myset_list:
if all(distance(p, kp) > threshold for kp in kept_points):
kept_points.append(p)
return kept_points
def solve_likePoints(myset):
#2 list
myset_list=list(myset)
threshold = 5 #阈值
#去除接近的点
filtered_points = remove_close_points(myset_list, threshold)
#如果需要,可以转换回集合(但注意这会丢失顺序)
filtered_set = set(filtered_points)
return filtered_set
def solve_lines(img,lines):
for line in lines:
for x1,y1,x2,y2 in line:
k=(y2-y1)/(x2-x1)
if k>0:
type1.append(line)
else:
type2.append(line)
for each1 in type1:
for x1,y1,x2,y2 in each1:
#print(x1,y1,x2,y2)
for each2 in type2:
for x3,y3,x4,y4 in each2:
point = intersection_point(x1, y1, x2, y2, x3, y3, x4, y4)
x,y=point
#print(x,y)
x_int=int(x)
y_int=int(y)
my_count.append((x_int,y_int))
cv2.circle(img0,(x_int,y_int),2,255,2)
my_set = set(my_count)
filtered_set = solve_likePoints(my_set)
print(filtered_set)
print(f"去重后(不保留顺序)的元素个数:{len(filtered_set)}")
img0=cv2.imread('./Ti/chessboard.png')
Gauss_img=gaussian_blur(img0,3)
Canny_img=canny_filter(Gauss_img,50,150)
ROI_img=roi_mask(Canny_img)
Hough_img,lines=hough_lines(ROI_img)
solve_lines(Hough_img,lines)
cv2.imshow('winname',img0)
cv2.waitKey()