文章目录
摘要
传统方法检测烟柱的数量
一、光学成像
盛放烟支的烟盒尺寸大致是1000mm*1000mm,穹顶光暂时无法覆盖该尺寸,现场采用4根条形光源分布在烟盒的四周做均匀光照射眼烟盒,采用分辨率为2592*1944的500万像素的灰度灰度相机
二、图像处理
1. 获取烟柱区域
1.1 原始图像如下所示:
1.2 烟柱的mask区域如下所示:
#3. getMaskImg
def getRoughBinImg(srcImg, grayVal):
ret, dst = cv2.threshold(srcImg, grayVal, 255, cv2.THRESH_BINARY)#固定阈值二值化
window = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7, 7)) #开操作
maskBinImg = cv2.morphologyEx(dst, cv2.MORPH_OPEN, window, iterations = 2)
bitMaskImg = cv2.bitwise_and(srcImg, srcImg, mask =maskBinImg) #roi的烟柱区域
return bitMaskImg, maskBinImg
2. 边界区域填充
2.1 测量数量的二值化图像采用动态二值化方法,因此在边界处的区域需要填充,否则会造成边界区域的图像是联通的,中间区域即使是分散的,如下图所示。
2.2 在边缘出的图形填充中心的图像。
#边界填充的中心image
def getEdgeFillImg(roiImg, maskBinImg):
#1. 大致的起始坐标
rectPos = getBoundRectPos(maskBinImg)
#2. 中心的rect
centRectImg = getScaleRoiImg(roiImg, rectPos)
#3. blackMask的填充
edgeFillImg = getEdgeImg(roiImg, maskBinImg, centRectImg)
return edgeFillImg
3. 二值化
动态二值化的两个关键参数,一个是滑动窗口,即邻域内像素的加权和,采用的是高斯还是均值。另一个参数是加权值减去这个常数。
#binImg的
def getSrcBinImg(roiImg, edgeFillImg, widowSize, constVal):
srcAddImg = cv2.addWeighted(roiImg, 1, edgeFillImg, 1, 0)
binImg = getSubBinImg(srcAddImg, widowSize, constVal)
return binImg
#adaptBin
def getSubBinImg(roiImg, widowSize, constVal):
binSizeTmp = 2*widowSize + 1 #20
binConstTmp = constVal - 50 #48
srcBinImg = cv2.adaptiveThreshold(roiImg, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY, binSizeTmp, binConstTmp)
return srcBinImg
4. 形态学后处理
部分烟柱有粘连,采用形态学后处理,进行行和列的分割, 分割后的效果如下所示。
#形态学
def getDstBinMorph(srcBinImg):
#总体2*2
window = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (2, 2))
dstBinImg = cv2.morphologyEx(srcBinImg, cv2.MORPH_OPEN, window, iterations = 1)
#行和列的分割
windowRow = cv2.getStructuringElement(cv2.MORPH_RECT, (6, 1))
windowLine = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 6))
dstBinImg1 = cv2.morphologyEx(dstBinImg, cv2.MORPH_OPEN, windowRow, iterations
= 1)
dstBinImg2 = cv2.morphologyEx(dstBinImg1, cv2.MORPH_OPEN, windowLine,
iterations = 1)
return dstBinImg2
5. 数量计算
代码:
#7. 近似的轮廓
def findBinRects(binImg):
allContours, _ = cv2.findContours(binImg, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if len(allContours) ==0:
print("error not find the contour pos")
return False
#计算轮廓面积
centPointList = []
contours = sorted(allContours, key = cv2.contourArea, reverse = True)
for subCount in contours:
subCountFlag, centPoint = getCheckCount(subCount)
if subCountFlag:
centPointList.append(centPoint)
return True, centPointList
总结
二值化图像,形态学后处理,注意边际的区域。
采用分割网络,如unet虽然稳定,但是标注花费较多人工成本,同时网络推倒时间较长。