一.实验要求
利用最小值滤波、图像形态学处理提取图像背景,通过图像减去背景得到待分割图像,由于去除了背景非均匀性因素,可采用阈值分割算法有效提取颗粒物,再对颗粒物进行计数处理。
二.设备及材料
1.PC机一台
2.pycharm
3.玉米、大米或枸杞等颗粒图像。
三.设计思路
这个程序实现了对颗粒图像进行处理和计数的功能。程序使用Python语言和OpenCV库实现了中值滤波、最小值滤波、二值化、形态学处理和连通区域计数等操作,可以对颗粒图像进行预处理和计数。
程序的逻辑思路是先读取颗粒图像,然后使用中值滤波对图像进行平滑处理,再使用二值化将图像转换为黑白二值图像。接着,程序使用最小值滤波对图像进行背景估计,然后将背景估计结果从原图像中减去,得到背景减除图像。再次使用二值化将背景减除图像转换为黑白二值图像。接下来,程序使用形态学处理对二值图像进行腐蚀和膨胀操作,去除噪声和连接颗粒。最,程序使用连通区域计数函数计算颗粒的数量,并将颗粒数量绘制在图像上。
程序的实现效果是可以对粒图像进行预处理和计数,可以去除背景噪声和连接颗粒,从而准确地计算颗粒数量。程序使用了OpenCV库提供的中值滤波、最小值滤波、二值化、形态学处理和连通区域计数函数,这些函数可以快速地对图像进行处理和计数,使得程序的实现更加简单和高效。通过这个程序,用户可以学习到如何使用Python实现颗粒图像处理和计数功能,同时也可以了解到中值滤波、最小值滤波、二值化、形态学处理和连通区域计数的原理和应用。
四.程序代码
import cv2
import numpy as np
# 中值滤波
def MedianFilter(img, w):
h = (w - 1) // 2
Img = np.zeros_like(img)
for i in range(img.shape[0]):
i0 = max(0, i - h)
i1 = min(img.shape[0], i + h + 1)
for j in range(img.shape[1]):
j0 = max(0, j - h)
j1 = min(img.shape[1], j + h + 1)
b = np.sort(img[i0:i1, j0:j1].flatten())
Img[i, j] = b[len(b) // 2]
return Img
# 最小值滤波
def MinFilter(img, w):
h = (w - 1) // 2
Img = np.zeros_like(img)
for i in range(img.shape[0]):
i0 = max(0, i - h)
i1 = min(img.shape[0], i + h + 1)
for j in range(img.shape[1]):
j0 = max(0, j - h)
j1 = min(img.shape[1], j + h + 1)
Img[i, j] = np.min(img[i0:i1, j0:j1])
return Img
# 读取图像
img = cv2.imread('grains.png')
cv2.imshow('Grains Image', img)
# 中值滤波
Img = MedianFilter(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), 5)
cv2.imshow('Median Filtered Image', Img)
# 二值化
thresh, bw = cv2.threshold(Img, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
cv2.imshow('Binarized Image', bw)
# 最小值滤波
fo = MinFilter(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), 21)
f2 = cv2.subtract(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), fo)
cv2.imshow('Background Subtracted Image', f2)
# 二值化
level, B2 = cv2.threshold(f2, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
cv2.imshow('Background Subtracted Binarized Image', B2)
# 形态学处理
se = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (6, 6))
B2 = cv2.erode(B2, se)
B2 = cv2.dilate(B2, se)
cv2.imshow('Morphologically Processed Image', B2)
# 计数
num, limg = cv2.connectedComponents(B2)
s = np.zeros(num)
for i in range(limg.shape[0]):
for j in range(limg.shape[1]):
if limg[i, j] != 0:
s[limg[i, j]] += 1
for i in range(num):
if s[i] < 20 or s[i] > 1600:
s[i] = 0
for i in range(limg.shape[0]):
for j in range(limg.shape[1]):
if limg[i, j] != 0:
limg[i, j] = s[limg[i, j]]
cv2.imshow('Counted Image', limg / np.max(limg))
print('颗粒计数:', num-1)
cv2.waitKey(0)
cv2.destroyAllWindows()
中值滤波后的图像
形态学处理后的图像
二值化后的图像
计数图像
背景减除后的图像
背景减除后的值化图像
颗粒图像