当前位置:   article > 正文

python opencv对颗粒的计数与计算空洞率_opencv 计算孔隙率

opencv 计算孔隙率

梳理下最近一个多星期的学习成果。

一、问题:计算颗粒数与空洞率

这次要计算的是下面这张图片,图像比较大,上传不了,先截图吧。预计颗粒数精确度为±5个,空洞率2%误差。

原始图像

二、计算颗粒数

    1.第一步是要裁剪图片,此处参考https://blog.csdn.net/liqiancao/article/details/55670749。裁剪后的图像如下:

ROI选取

2.因为空白区域有很多的噪声干扰点(小图看不清楚),如果直接进行图片处理的话对后续操作有很大影响。所以我们还要选取ROI(感兴趣区域)。左边是噪声放大图,右边可以点击放大。

选取ROI区域ROI区域

3.现在才算要开始处理了,先选取单通道图像,把BGR图像转为灰度图。并且在二值化之前对图形进行滤波处理,可以使用高斯滤波(处理正态分布噪声),方向滤波,中值滤波,还有形态学滤波等。这里因为目标元素的颜色深浅不一致,所以用2D卷积核进行模糊处理。

2D卷积处理

4.接下来进行二值化处理,因为图像各处深浅不一致,所以使用自适应二值化的方法处理,其中的参数看情况调整。

12

5.在二值化后,可以看到有些颗粒是黏在一起的,有的颗粒形状怪异,所以在二值化后也要对图像进行形态学处理。这里运用开运算来去除图中的白点。不过图中还是有些比较大的噪声没处理掉,没办法,如果处理了会把有些小的目标颗粒也去除了。所以只能选择误差最小的做法。

666

6.接下来就是对颗粒的轮廓进行提取并且统计数目。在这里因为有的颗粒黏在一起让轮廓变大,所以做了判断,太小的噪声去除,太大的去除,在一定区间内的认定为连体颗粒,然后计算时按两个算。

5553333

7.计算结果

3333

8.结论

最后通过肉眼对比验证(眼睛真的受伤),误差为7±2,7为缺少,2为过多,emmmm,算勉强到达合格线吧。空洞率还在校正。想计算出最精确再来写

最后附上代码:

  1. # -*- coding:utf-8 -*-
  2. import cv2 #导入opencv模块
  3. import numpy as np
  4. import time
  5. def timeit(func):
  6. def test(*args, **kwargs):
  7. start = time.clock()
  8. res = func(*args, **kwargs)
  9. end = time.clock()
  10. print("{}函数用时为:{}分{}秒".format(func.__name__, (end - start) // 60,
  11. (end - start) % 60))
  12. return res
  13. return test
  14. #剪切出ROI区域
  15. def picture_cut(Img):
  16. image = cv2.imread(Img)
  17. image2 = image.copy()
  18. gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
  19. gradX = cv2.Sobel(gray, cv2.CV_32F, dx=1, dy=0, ksize=-1)
  20. gradY = cv2.Sobel(gray, cv2.CV_32F, dx=0, dy=1, ksize=-1)
  21. gradient = cv2.subtract(gradX, gradY)
  22. gradient = cv2.convertScaleAbs(gradient)
  23. blurred = cv2.blur(gradient, (9, 9))
  24. _, thresh = cv2.threshold(blurred, 90, 255, cv2.THRESH_BINARY)
  25. kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
  26. closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
  27. closed = cv2.erode(closed, None, iterations=4)
  28. closed = cv2.dilate(closed, None, iterations=4)
  29. (cnts, _) = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL,
  30. cv2.CHAIN_APPROX_SIMPLE)
  31. c = sorted(cnts, key=cv2.contourArea, reverse=True)[0]
  32. rect = cv2.minAreaRect(c)
  33. box = np.int0(cv2.boxPoints(rect))
  34. cv2.drawContours(image, [box], -1, (0, 255, 0), 1)
  35. Xs = [i[0] for i in box]
  36. Ys = [i[1] for i in box]
  37. x1 = min(Xs)
  38. x2 = max(Xs)
  39. y1 = min(Ys)
  40. y2 = max(Ys)
  41. hight = y2 - y1
  42. width = x2 - x1
  43. cropImg = image2[y1:y1 + hight, x1:x1 + width]
  44. return cropImg
  45. # cv2.imwrite("before4.jpg", cropImg)
  46. #对ROI区域进一步进行处理
  47. def select_background(background, prospect):
  48. img = cv2.imread(background) #背景图
  49. oriimg = cv2.imread(prospect)
  50. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  51. mask = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR) #img是腐蚀膨胀完的图片
  52. # cv_show(oriimg, "oriimg")
  53. # cv_show(mask, "mask")
  54. ROI = cv2.bitwise_and(mask, oriimg) #oriimg是原始图片 做与运算
  55. return ROI
  56. # cv2.imwrite("test.jpg", ROI)
  57. #灰度加模糊处理
  58. def picture_filter2D(picture):
  59. img = cv2.imread(picture) #导入图片,图片放在程序所在目录
  60. img = img.copy()
  61. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #转换为灰度图
  62. kernel = np.ones((4, 4), np.float32) / 16
  63. dst = cv2.filter2D(gray, -1, kernel) #2D卷积核模糊处理
  64. return dst
  65. #自适应二值化
  66. def picture_adaptive(dst):
  67. cloesd1 = cv2.adaptiveThreshold(dst, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
  68. cv2.THRESH_BINARY_INV, 13, 6)
  69. return cloesd1
  70. #形态学处理
  71. def picture_open(cloesd1):
  72. element = cv2.getStructuringElement(cv2.MORPH_RECT,
  73. (2, 4)) #形态学去噪 24效果最佳
  74. cloesd2 = cv2.morphologyEx(cloesd1, cv2.MORPH_OPEN, element) #开运算去噪
  75. return cloesd2
  76. # #画轮廓并且统计数目
  77. @timeit
  78. def contour_count(cloesd2, img):
  79. img = cv2.imread(img)
  80. contours, hierarchy = cv2.findContours(cloesd2, cv2.RETR_TREE,
  81. cv2.CHAIN_APPROX_SIMPLE) #轮廓检测函数
  82. cv2.drawContours(cloesd2, contours, -1, (0, 255, 0), 3) #绘制轮廓
  83. count = 0 #总数
  84. ares_avrg = 0 #平均
  85. count_small = 0 #小的颗粒数
  86. count_big = 0 #大的颗粒数
  87. big = 25
  88. small = 2.2
  89. #遍历找到的所有颗粒
  90. for cont in contours:
  91. ares = cv2.contourArea(cont) #计算包围形状的面积
  92. if ares > big and ares < 100: #过滤面积大于big数值的形状
  93. count_big += 1
  94. x, y, w, h = cv2.boundingRect(cont)
  95. cv2.rectangle(img, (x, y), (x + w, y + h), (0,0,255),
  96. 1) #绘制矩形 绿色
  97. continue
  98. if ares < small: #过滤面积小于small数值的形状
  99. count_small += 1
  100. continue
  101. if ares > 100:
  102. continue
  103. count += 1 #总体计数加1
  104. x, y, w, h = cv2.boundingRect(cont) #提取水平矩形坐标
  105. cv2.rectangle(img, (x, y), (x + w, y + h), (0,0,255), 1) #绘制矩形 红色
  106. print("总数为{},面积大于{}的颗粒数为{},面积小于{}的颗粒数为{},一共是{}颗!".format(
  107. count, big, count_big, small, count_small, count + (count_big * 2)))
  108. cv2.imwrite("after.jpg", img)
  109. #显示图片
  110. def cv_show(img, name):
  111. cv2.namedWindow(name, 1)
  112. cv2.imshow(name, img)
  113. cv2.waitKey(0)
  114. cv2.destroyAllWindows()
  115. if __name__ == "__main__":
  116. path = "ROI1.jpg"
  117. dst = picture_filter2D(path)
  118. cv2.imwrite("filter2D.jpg", dst)
  119. cloesd1 = picture_adaptive(dst)
  120. cv2.imwrite("thresh_binary.jpg", cloesd1)
  121. cloesd2 = picture_open(cloesd1)
  122. cv2.imwrite("morph_open.jpg", cloesd2)
  123. contour_count(cloesd2, path)

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/72422?site
推荐阅读
相关标签
  

闽ICP备14008679号