优化,解决bug后
import cv2
import numpy as np
import os
import matplotlib.pyplot as plt
def imageProcess(image):
_, binary = cv2.threshold(image, 28, 255, cv2.THRESH_BINARY)
dilate_img = cv2.dilate(binary, kernel=np.ones((3, 3), np.uint8))
erode_img = cv2.erode(dilate_img, kernel=np.ones((3, 3), np.uint8))
# 轮廓
contours, hierarchy = cv2.findContours(erode_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
newImg = np.zeros(gray.shape, dtype=np.uint8)
Contour = cv2.drawContours(newImg, contours, -1, 255, 1)
return Contour
# 霍夫直线检测
def houghStraightLines(imgContour):
# dilate_img = cv2.dilate(imgContour, kernel=np.ones((1, 1), np.uint8))
_, binary = cv2.threshold(imgContour, 28, 255, cv2.THRESH_BINARY)
dilate_img = cv2.dilate(binary, kernel=np.ones((3, 3), np.uint8))
dilate_img = cv2.erode(dilate_img, kernel=np.ones((3, 3), np.uint8))
# cv2.imshow("dilate_img", dilate_img)
contours, hierarchy = cv2.findContours(dilate_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
newImg = np.zeros(imgContour.shape, dtype=np.uint8)
imgContour = cv2.drawContours(newImg, contours, -1, 255, 1)
# 霍夫变换
minLineLength = 40 # 56
maxLineGap = 0
lines = cv2.HoughLines(imgContour, 1.0, np.pi / 180, minLineLength, maxLineGap) # 函数将通过步长为1的半径和步长为π/180的角来搜索所有可能的直线
# print(len(lines))
if lines is None:
return -1
else:
number = 0
linesR = []
linesTheta = []
xPoints = []
yPoints = []
for line in lines:
rho, theta = line[0] # line[0]存储的是点到直线的极径和极角,其中极角是弧度表示的
a = np.cos(theta) # 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)) # 直线终点纵坐标
# x1 = int(x0 + 1000/2 * (-b)) # 直线起点横坐标
# y1 = int(y0 + 1000/2 * (a)) # 直线起点纵坐标
# x2 = int(x0 - 1000/2 * (-b)) # 直线终点横坐标
# y2 = int(y0 - 1000/2 * (a)) # 直线终点纵坐标
# 删除外面的四条边线
threshold_value = 8
if (abs(x1) < threshold_value or abs(y1) < threshold_value) and \
(abs(x2) < threshold_value or abs(y2) < threshold_value):
continue
elif (abs(abs(x1) - 1000) < threshold_value or abs(abs(y1) - 1000) < threshold_value) and \
(abs(abs(x2) - 1000) < threshold_value or abs(abs(y2) - 1000) < threshold_value):
continue
elif (abs(x1 - 640/2) < threshold_value or abs(y1 - 480/2) < threshold_value) and \
(abs(x2 - 640/2) < threshold_value or abs(y2 - 480/2) < threshold_value):
continue
cv2.line(imgContour, (x1, y1), (x2, y2), (0, 255, 0), 2)
# 检测出多少条线
# number += 1
# print(number)
linesR.append(abs(rho))
linesTheta.append(theta)
xPointsList = [x1, y1]
yPointsList = [x2, y2]
xPoints.append(xPointsList)
yPoints.append(yPointsList)
# cv2.imshow("Find_lines", imgContour)
# cv2.waitKey()
newLinesR = []
newXPoints = []
newYPoints = []
if len(linesTheta) >= 3:
# 找到相同的元素和下标
list_same = []
for i in linesTheta:
address_index = [x for x in range(len(linesTheta)) if linesTheta[x] == i]
list_same.append([i, address_index])
dict_address = dict(list_same)
for values in dict_address.values():
# print(len(values))
if len(values) >= 2:
index = values
newLinesR.append(linesR[index[0]])
newLinesR.append(linesR[index[1]])
# 获取平行线坐标
newXPoints.append(xPoints[index[0]])
newXPoints.append(xPoints[index[1]])
newYPoints.append(yPoints[index[0]])
newYPoints.append(yPoints[index[1]])
break
elif len(linesTheta) == 2 and linesTheta[0] == linesTheta[1]:
newLinesR.append(linesR[0])
newLinesR.append(linesR[1])
else:
return -1
# 计算两线间距离
dist_many = []
if len(newLinesR) % 2 == 0:
for j in range(int(len(newLinesR) / 2)):
dist_one = abs(newLinesR[j * 2] - newLinesR[2 * j + 1])
if dist_one > 5 and dist_one < 100:
dist_many.append(dist_one)
if len(dist_many) > 0:
distance = sum(dist_many) / len(dist_many)
# 设置间距的最大值
print("distance hough is ", distance)
# 在图像上显示距离
# cv2.putText(imgContour, ("min_dist=%0.2f" % distance), (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)
# 绘制平行线
for k in range(len(newXPoints)):
cv2.line(imgContour, (newXPoints[k][0], newXPoints[k][1]), (newYPoints[k][0], newYPoints[k][1]),
(0, 255, 0), 2)
# print(len(newXPoints))
# print("newXPoints :", newXPoints)
# cv2.imshow("image", imgContour)
# cv2.waitKey()
if distance > 1 and distance < 100:
return distance
else:
return -1
else:
return -1
else:
# print("检测位置不合理")
return -1
def main(image):
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
#
# 二值化
_, binary = cv2.threshold(gray, 28, 255, cv2.THRESH_BINARY)
# 图像取反
# wiseImg = cv2.bitwise_not(binary)
# cv2.imshow("binary", binary)
# 膨胀腐蚀操作
dilate_img = cv2.dilate(binary, kernel=np.ones((3, 3), np.uint8))
dilate_img = cv2.erode(dilate_img, kernel=np.ones((3, 3), np.uint8))
# cv2.imshow("bin_img", dilate_img)
# cv2.waitKey()
# 轮廓
contours, hierarchy = cv2.findContours(dilate_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
newImg = np.zeros(gray.shape, dtype=np.uint8)
imgContour = cv2.drawContours(newImg, contours, -1,255,1)
# cv2.imshow("imgContour", imgContour)
# cv2.waitKey()
# 获取图像长宽
imgInfo = image.shape
height = imgInfo[0]
width = imgInfo[1]
dilate_img = cv2.dilate(imgContour, kernel=np.ones((1, 1), np.uint8))
# cv2.imshow("dilate_img", dilate_img)
# 霍夫变换
minLineLength = 80
maxLineGap = 0
lines = cv2.HoughLines(dilate_img, 1.0, np.pi / 180, minLineLength, maxLineGap) # 函数将通过步长为1的半径和步长为π/180的角来搜索所有可能的直线
# print(len(lines))
if len(lines) >= 2:
number = 0
linesR = []
linesTheta1 = []
xPoints = []
yPoints = []
for line in lines:
rho, theta = line[0] # line[0]存储的是点到直线的极径和极角,其中极角是弧度表示的
a = np.cos(theta) # 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)) # 直线终点纵坐标
# 删除外面的四条边线
threshold_value = 10
if (abs(x1) < threshold_value or abs(y1) < threshold_value) and \
(abs(x2) < threshold_value or abs(y2) < threshold_value):
continue
elif (abs(x1 - 640 ) < threshold_value or abs(y1 - 480) < threshold_value) and \
(abs(x2 - 640 ) < threshold_value or abs(y2 - 480) < threshold_value):
continue
# cv2.line(image, (x1, y1), (x2, y2), (0, 255, 0), 2)
# 检测出多少条线
# number += 1
# print(number)
linesR.append(abs(rho))
linesTheta1.append(theta)
xPointsList = [x1, y1]
yPointsList = [x2, y2]
xPoints.append(xPointsList)
yPoints.append(yPointsList)
# cv2.imshow("Find_lines", image)
# cv2.waitKey()
# print(linesR)
# print(linesTheta1)
# print(xPoints)
newLinesR = []
newXPoints = []
newYPoints = []
if len(linesTheta1) >= 3:
# 找到相同的元素和下标 平行线
list_same = []
for i in linesTheta1:
address_index = [x for x in range(len(linesTheta1)) if linesTheta1[x] == i]
list_same.append([i, address_index])
dict_address = dict(list_same)
for values in dict_address.values():
# print(values)
if len(values) >= 2:
index = values
newLinesR.append(linesR[index[0]])
newLinesR.append(linesR[index[1]])
# 获取平行线坐标
newXPoints.append(xPoints[index[0]])
newXPoints.append(xPoints[index[1]])
newYPoints.append(yPoints[index[0]])
newYPoints.append(yPoints[index[1]])
# 计算两线间距离
dist_many = []
if len(newLinesR) % 2 == 0:
for j in range(int(len(newLinesR) / 2)):
dist_one = abs(newLinesR[j * 2] - newLinesR[2 * j + 1])
if dist_one > 5 and dist_one < 100:
dist_many.append(dist_one)
if len(dist_many) > 0:
distance = sum(dist_many) / len(dist_many)
# 设置间距的最大值
print("distance is ", distance)
# 在图像上显示距离
if distance > 1 and distance < 100:
cv2.putText(imgContour, ("min_dist=%0.2f" % distance), (50, 50),
cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)
# 绘制平行线
for k in range(len(newXPoints)):
cv2.line(image, (newXPoints[k][0], newXPoints[k][1]), (newYPoints[k][0], newYPoints[k][1]), (0, 255, 0), 2)
# print(len(newXPoints))
# print("newXPoints :", newXPoints)
break
# -----------------------------------应该只算一次
else:
dists = []
for i in range(2):
for j in range(2):
# print(j)
img_roi = dilate_img[(i * 240):(i + 1) * 240, (j * 320):((j + 1) * 320)]
namejpg = "Images/smalls" + str(i)+ str(j) + ".jpg"
cv2.imwrite(namejpg,img_roi)
# cv2.imshow("roi", img_roi)
# cv2.waitKey()
dist = houghStraightLines(img_roi)
if dist > 0:
dists.append(dist)
if sum(dists) > 0:
dis_final = sum(dists) / len(dists)
print("final distance 3333 is ", dis_final)
else:
print("请调整测量位置3")
break
elif len(linesTheta1) == 2 and linesTheta1[0] == linesTheta1[1]:
distance = abs(linesR[0] - linesR[1])
print("distance 44444 is ", distance)
else:
dists = []
num = 0
for i in range(2):
for j in range(2):
# print(j)
img_roi = dilate_img[(i * 240):(i + 1) * 240, (j * 320):((j + 1) * 320)]
hough_roi = img_roi.copy()
namejpg = "Images/smalls" + str(i) + str(j) + ".jpg"
cv2.imwrite(namejpg, img_roi)
# cv2.imshow("roi", hough_roi)
# cv2.waitKey()
dist = houghStraightLines(hough_roi)
if dist > 0:
dists.append(dist)
if sum(dists) > 0:
dis_final = sum(dists) / len(dists)
print("final distance 2222 is ", dis_final)
else:
print("调整位置2")
else:
dists = []
for i in range(2):
for j in range(2):
# print(j)
img_roi = dilate_img[(i * 240):(i+1)*240, (j * 320):((j+1)* 320)]
# namejpg = "Images/smalls" + str(i)+ str(j) + ".jpg"
# cv2.imwrite(namejpg,img_roi)
# cv2.imshow("roi", img_roi)
# cv2.waitKey()
dist = houghStraightLines(img_roi)
if dist > 0:
dists.append(dist)
if sum(dists) > 0:
dis_final = sum(dists)/len(dists)
print("final distance 1111 is ", dis_final)
else:
print("请调整检测位置1")
# cv2.imshow('dis_lines',image)
# cv2.waitKey()
plt.imshow(image)
plt.show()
if __name__ == "__main__":
#
# capture = cv2.VideoCapture(0)
#
# if capture is None:
# print("Fail to open camera")
# else:
# while (True):
# # 获取一帧
# ret, frame = capture.read()
# # 将这帧转换为灰度图
# # gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# main(frame)
#
# # cv2.imshow('frame', frame)
# if cv2.waitKey(1) == ord('q'):
# break
文件夹所有图片
path = r"D:\BUFFER\Pycharm\Detect Line\photos"
for filename in os.listdir(path): # listdir的参数是文件夹的路径
filenames = path + '\\' + filename
# print(filenames)
img_orig = cv2.imread(filenames, 1)
print(filenames)
if img_orig is None:
print("Warning: No Pictures")
else:
# image = cv2.imread("Images/lines.bmp",1)
# cv2.imshow("gray_lines", image)
# imgContour = imageProcess(gray)
main(img_orig)
# 单张处理
# # # read the image 并做预处理
# image = cv2.imread("photos/Check_021.jpg",1)
# # # image = cv2.imread("Images/Snap_005.jpg",1)
#
# if image is None:
# print("Warning: No Pictures")
# else:
# # image = cv2.imread("Images/lines.bmp",1)
# # cv2.imshow("gray_lines", image)
# # imgContour = imageProcess(gray)
# main(image)