python + openCV 实现图像轮廓识别和面积计算

python + openCV 实现图像轮廓识别和面积计算_第1张图片
需求:以上图像是金属/丝状物/金属三层夹心结构,希望通过opencv计算出丝状物在两金属所形成带隙中的面积占比。
拟解决思路:二值分割 + 滤波(形态学)+ 轮廓提取,路线如下图。python + openCV 实现图像轮廓识别和面积计算_第2张图片
以下是具体代码

import  cv2
import tkinter
import numpy as np
from matplotlib import pyplot as plt

#定义线性增强函数,为增强区间
def linear_threshold(Image,h,w,x1,x2,z2,z1 = 0,z3 = 0):

    for i in range(0, h):
        for j in range(0, w):
            tmp = Image[i, j]
            if tmp < x1:
                Image[i, j] = z1
            elif tmp >= x1 and tmp < x2:
                Image[i, j] = z2
            else:
                Image[i, j] = z3

    return Image

#轮廓面积计算函数
def areaCal(contour):

    area = 0
    for i in range(len(contour)):
        area += cv2.contourArea(contour[i])

    return area

接下来就是主函数了

if __name__ == '__main__':
    #读入图片
    img = cv2.imread('C-1-P.tif',0)
    #设置掩模,将处理图像聚焦到夹层处
    mask = np.zeros(img.shape[:2],np.uint8)
    #掩模尺寸
    mask[800:1100,100:2400] = 255
    masked_img = cv2.bitwise_and(img,img,mask = mask)
    # 灰度直方图
    hist_mask = cv2.calcHist([img], [0], mask, [256], [0, 256])
    #突出前景,增强图像特征,阈值<26,200>是根据直方图像粗略估计而得,由于直方图是单峰(图片略渣),暂不知解决方案,有待修改。
    threshold_image = linear_threshold(masked_img,1920,2560,26,200,255)
    #中值滤波
    median1 = cv2.medianBlur(threshold_image,5)

接下来就是利用matplotlib生成所有图像

# 生成图像
    plt.subplot(2,2,1),plt.imshow(img,'gray')
    plt.subplot(2,2,2),plt.imshow(threshold_image,'gray')                                              
    plt.subplot(2, 2, 3), plt.plot(hist_mask)
    plt.subplot(2, 2, 4), plt.imshow(median1, 'gray')
    plt.show()

最后就是面积计算,第一步生成轮廓图像,第二步利用轮廓面积计算函数将所有轮廓累加求和。

    Image = np.zeros((1920, 2560), np.uint8)
    #cv2.findContours()有三个参数:1、输入图像;2、轮廓;3、层析结构。返回值有三个,其中第二个返回值是python列表,存储所有轮廓,且每一个轮廓都是Numpy数组,包含对象边界点(x,y)坐标。其余两返回值可参考openCV中文文档。
    image,contours,hierarchv = cv2.findContours(median1,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)   
    color = cv2.cvtColor(Image,cv2.COLOR_GRAY2BGR)
    #将轮廓在Image中生成
    Image = cv2.drawContours(color,contours,-1,(0,0,255),1)
    plt.imshow(Image)
    plt.show()
    #得到轮廓面积并打印
    print(areaCal(contours))

最后,将轮廓面积除以总面积即得到所需值。
python + openCV 实现图像轮廓识别和面积计算_第3张图片

**总结与不足:
由于图像灰度比较集中,仅有一个峰,不知道该如何确定最佳阈值,需要改进,也希望Homie们能提供宝贵意见,感激不尽。**

你可能感兴趣的:(数字图像处理,python,opencv)