如何使用OpenCV实现太阳能板图像的栅格线精准检测?
基于OpenCV的太阳能板栅格检测实现方案
问题概述
需求为针对包含太阳能板的输入图像,精准提取所有栅格线、过滤无关背景区域,完成全图栅格的完整检测。
- 原始参考图像:

- 原有代码输出效果:

原有代码核心问题:拉普拉斯边缘检测对细碎噪声过于敏感,且阈值函数参数设置错误(maxval传入0、阈值边界设为0,THRESH_TOZERO模式几乎没有二值化筛选效果),仅靠轮廓面积筛选完全无法区分栅格线和杂边、污渍轮廓,最终检测结果杂点多、栅格缺失严重。
原有实现代码如下:
image = cv2.imread("solar3.jpg") cv2.imshow("Image", image) image = cv2.resize(image, (482,406)) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) cv2.imshow("gray", gray) blur = cv2.GaussianBlur(gray, (0,0), 2) cv2.imshow("blur", blur) lap = cv2.Laplacian(blur, cv2.CV_32F) cv2.imshow("lap",lap) _,thresh = cv2.threshold(lap, 0, 0, cv2.THRESH_TOZERO) cv2.imshow("thresh", thresh) thresh = thresh.astype(np.uint8) contours, hierachy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) c = 0 for i in contours: area = cv2.contourArea(i) if area > 1000/2: cv2.drawContours(image, contours, c, (0, 255, 0), 2) c+=1 cv2.imshow("Final Image", image) cv2.waitKey(0)
优化实现思路
太阳能板栅格本身是等间距、互相垂直的水平/垂直规则线条结构,针对这个特征做定向提取,稳定性远高于普通边缘+轮廓筛选方案,核心逻辑:
- 预处理换双边滤波,平滑电池片表面噪点的同时不会糊掉栅格的锐利边缘
- 二值化用自适应高斯阈值,适配图像上不均匀的光照,避免亮部过检、暗部漏检
- 用水平、垂直方向的长条形形态学核做开运算,只保留对应方向的长线条,直接滤掉大部分杂散短边缘、污渍轮廓
- 合并横竖线检测结果后做一次闭运算,补全栅格上断开的小缺口
- 最后用概率霍夫直线做二次筛选,只保留角度接近水平/垂直、长度达标的线条,彻底过滤残留杂线
优化后可运行代码
import cv2 import numpy as np # 读取并统一图像尺寸 img = cv2.imread("solar3.jpg") img = cv2.resize(img, (482, 406)) result = img.copy() gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 保边去噪 blur = cv2.bilateralFilter(gray, 9, 75, 75) # 自适应阈值二值化,应对光照不均场景 thresh = cv2.adaptiveThreshold( blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 15, 2 ) # 生成水平、垂直方向专属形态学核 kernel_horizontal = cv2.getStructuringElement(cv2.MORPH_RECT, (25, 1)) kernel_vertical = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 25)) # 分别提取横向、纵向栅格 horizontal_grid = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel_horizontal, iterations=2) vertical_grid = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel_vertical, iterations=2) # 合并栅格掩码并补全断线缺口 grid_mask = cv2.add(horizontal_grid, vertical_grid) kernel_close = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3)) grid_mask = cv2.morphologyEx(grid_mask, cv2.MORPH_CLOSE, kernel_close, iterations=1) # 霍夫直线检测筛选有效栅格线 lines = cv2.HoughLinesP( grid_mask, 1, np.pi/180, threshold=50, minLineLength=30, maxLineGap=5 ) # 绘制符合角度、长度要求的栅格线 if lines is not None: for line in lines: x1, y1, x2, y2 = line[0] # 计算直线角度,仅保留水平/垂直方向线条(允许5度误差) line_angle = abs(np.arctan2(y2 - y1, x2 - x1) * 180 / np.pi) if line_angle < 5 or abs(line_angle - 90) < 5: cv2.line(result, (x1, y1), (x2, y2), (0, 255, 0), 2) # 输出检测结果 cv2.imshow("Solar Grid Detection Result", result) cv2.waitKey(0) cv2.destroyAllWindows()
参数调优说明
- 如果出现栅格漏检,可适当缩小方向形态学核的尺寸(如将25调整为20),或调低霍夫检测的
threshold、minLineLength参数 - 如果残留杂线过多,可适当增大方向形态学核尺寸,收紧角度筛选的误差范围,或增加小轮廓过滤步骤剔除孤立短线段
内容的提问来源于stack exchange,提问作者sweety
相关产品推荐
相关产品推荐

