检测十字标 opencv python
十字标是正的
def detect_cross_by_projection(image_path, k=1.0, sigma=1.0):# 1. 读取图像并转换为灰度图image = cv2.imread(image_path)if image is None:print("无法读取图像,请检查路径!")return Nonegray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 图片旋转5°rows, cols = image.shape[:2]M = cv2.getRotationMatrix2D((cols/2, rows/2), 3, 1)image = cv2.warpAffine(gray, M, (cols, rows))# 2. 边缘检测(Canny)edges = cv2.Canny(image, 100, 200, apertureSize=3)# 3. 统计行和列的边缘像素和(投影)row_projection = np.sum(edges, axis=1) # 行投影col_projection = np.sum(edges, axis=0) # 列投影# 4. 高斯平滑投影曲线row_projection_smooth = cv2.GaussianBlur(row_projection.astype(np.float32), (0, 0), sigma)col_projection_smooth = cv2.GaussianBlur(col_projection.astype(np.float32), (0, 0), sigma)# 5. 检测峰(局部极大且大于 mean + k*std)def detect_peaks(projection, k):mean = np.mean(projection)std = np.std(projection)threshold = mean + k * stdpeaks = []for i in range(1, len(projection) - 1):if projection[i] > projection[i-1] and projection[i] > projection[i+1] and projection[i] > threshold:peaks.append(i)return peaksrow_peaks = detect_peaks(row_projection_smooth, k)col_peaks = detect_peaks(col_projection_smooth, k)# 6. 取最显著的行峰和列峰if not row_peaks or not col_peaks:print("未检测到峰!")return None# 选择最显著的峰(投影值最大的峰)row_peak = row_peaks[np.argmax(row_projection_smooth[row_peaks])]col_peak = col_peaks[np.argmax(col_projection_smooth[col_peaks])]# 7. 计算交点并可视化cross_point = (col_peak, row_peak)# 绘制检测结果result_image = image.copy()cv2.circle(result_image, cross_point, 10, (0, 0, 255), -1) # 绘制交点cv2.line(result_image, (0, row_peak), (result_image.shape[1], row_peak), (0, 0, 255), 2) # 绘制行线cv2.line(result_image, (col_peak, 0), (col_peak, result_image.shape[0]), (0, 0, 255), 2) # 绘制列线# 8. 可视化投影曲线和峰plt.figure(figsize=(12, 6))# 行投影plt.subplot(1, 2, 1)plt.plot(row_projection, label="Row Projection")plt.plot(row_projection_smooth, label="Smoothed Row Projection")plt.axhline(y=np.mean(row_projection_smooth) + k * np.std(row_projection_smooth), color='r', linestyle='--', label="Threshold")plt.scatter(row_peaks, row_projection_smooth[row_peaks], color='g', label="Peaks")plt.title("Row Projection")plt.legend()# 列投影plt.subplot(1, 2, 2)plt.plot(col_projection, label="Column Projection")plt.plot(col_projection_smooth, label="Smoothed Column Projection")plt.axhline(y=np.mean(col_projection_smooth) + k * np.std(col_projection_smooth), color='r', linestyle='--', label="Threshold")plt.scatter(col_peaks, col_projection_smooth[col_peaks], color='g', label="Peaks")plt.title("Column Projection")plt.legend()plt.tight_layout()plt.show()# 9. 显示中间图和结果图cv2.imshow("image", image)cv2.imshow("Result", result_image)cv2.waitKey(0)cv2.destroyAllWindows()print("Detected Cross Point:", cross_point)
原图
统计垂直方向和水平方向
马上就能找到中点了
但是一旦图像旋转了3°,这个算法立马失效,比如下面的