基于计算机视觉的钢板计数

功能:

根据堆叠钢板的照片计算出其中的钢板数量


思路

相邻钢板之间的空隙在垂直方向灰度分布上会呈现出波峰,因此可以先将图像锐化以增强边界对比度,然后计算垂直方向(默认钢板水平放置)梯度,此时的垂直方向灰度分布会出现许多波峰,在设置好阈值与波峰宽度后可据此计算出钢板数量


实现

读入图片

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imdecode(np.fromfile(r'图片路径', dtype=np.uint8), 0)
cv2.imshow("img", img)

基于计算机视觉的钢板计数_第1张图片

锐化

sharpen_op = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]], dtype=np.float32)
sharpen_image = cv2.filter2D(img, cv2.CV_32F, sharpen_op)
sharpen_image = cv2.convertScaleAbs(sharpen_image)
cv2.imshow("sharpen_image", sharpen_image)

基于计算机视觉的钢板计数_第2张图片

计算垂直梯度

dst = cv2.Sobel(sharpen_image, -1, 0, 1)
cv2.imshow("dst", dst)

基于计算机视觉的钢板计数_第3张图片

归一化灰度值

此处的垂直方向灰度分布采取计算行灰度均值的方式

list_ = []
for i in range(dst.shape[0]):
	# 选取前200列,视图像而定
    list_.append(int(np.floor(sum(dst[i, :200] / 200))))
max_ = max(list_)
for i in range(len(list_)):
    list_[i] = list_[i] / max_
    
plt.plot(list_)
plt.show()

基于计算机视觉的钢板计数_第4张图片

计数

峰值宽度由人为调整参数获得,此处尚未找到合理计算方式

sum_ = 0
peakWidth = len(list_)/200  # 峰的宽度,用于排除临近的次峰值
id = 0  # 标记最近的峰位置
for i in range(1,len(list_)):
    if list_[i] > 0.4:
        if i-id > peakWidth:
            sum_ += 1
            id = i
print("sum = ", sum_)
sum = 76  # 最终误差在3以内

存在问题

1、计算垂直灰度分布所采用方式仅对左对齐且处于图像左边的钢板堆有效
2、波峰数目确定中的波峰宽度无法自动确定,参数只对部分图像有效,计算方式可解释性不强

你可能感兴趣的:(计算机视觉,opencv,python)