算法:
第一步,将图片转换为二值图像A
第二步,创建和A相同大小但是元素都为0的图像B,并复制A到A_copy中
第三步,A中任选一点值为255的像素,设为p1,并使用计算连通分量算法,当算法收敛时,则检测出一个连通分量
第四步,将检测出来的连通分量复制到B中,A_copy中对应的值设为0,记录连通分量和像素数量
第五步,重复第三步和第四步,直到A_copy中所有的像素值为0,检测出所有连通分量
import cv2 import numpy as np path = "_cc.png" img_A = cv2.imread(path) gray_A = cv2.cvtColor(img_A, cv2.COLOR_BGR2GRAY) #转换成灰度图 ret, thresh_A = cv2.threshold(gray_A, 50, 255, cv2.THRESH_BINARY_INV) #灰度图转换成二值图像 thresh_A_copy = thresh_A.copy() #复制thresh_A到thresh_A_copy thresh_B = np.zeros(gray_A.shape, np.uint8) #thresh_B大小与A相同,像素值为0 kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))#3×3结构元 count = [ ] #为了记录连通分量中的像素个数 #循环,直到thresh_A_copy中的像素值全部为0 while thresh_A_copy.any(): Xa_copy, Ya_copy = np.where(thresh_A_copy > 0) #thresh_A_copy中值为255的像素的坐标 thresh_B[Xa_copy[0]][Ya_copy[0]] = 255 #选取第一个点,并将thresh_B中对应像素值改为255 #连通分量算法,先对thresh_B进行膨胀,再和thresh_A执行and操作(取交集) for i in range(200): dilation_B = cv2.dilate(thresh_B, kernel, iterations=1) thresh_B = cv2.bitwise_and(thresh_A, dilation_B) #取thresh_B值为255的像素坐标,并将thresh_A_copy中对应坐标像素值变为0 Xb, Yb = np.where(thresh_B > 0) thresh_A_copy[Xb, Yb] = 0 #显示连通分量及其包含像素数量 count.append(len(Xb)) if len(count) == 0: print("无连通分量") if len(count) == 1: print("第1个连通分量为{}".format(count[0])) if len(count) >= 2: print("第{}个连通分量为{}".format(len(count), count[-1] - count[-2])) cv2.imshow("A", thresh_A) cv2.imshow("A_copy", thresh_A_copy) cv2.imshow("B", thresh_B) cv2.waitKey(0)