美文网首页
Python视觉识别--OpenCV反射投影\模板匹配\图像二值

Python视觉识别--OpenCV反射投影\模板匹配\图像二值

作者: 无剑_君 | 来源:发表于2020-02-27 11:26 被阅读0次

    (十四)反射投影

    简单的说就是通过给定的直方图信息,在图像找到相应的像素分布区域。
    反射投影的应用
    物体跟踪、定位物体等

    import cv2 as cv
    from matplotlib import pyplot as plt
    
    
    def hist2d(image):
        """2d 直方图计算和现实"""
        # 转换为hsv色彩空间
        hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV)
        # [180,256] bins 越多对每个像素细分的越厉害,会导致反响直方图的碎片化
        # [0,180,0,256]:hsv色彩空间中 h和s的取值范围,只是固定的
        hist = cv.calcHist([image], [0, 1], None, [180, 256], [0, 180, 0, 256])
        # interpolation:差值方式
        plt.imshow(hist, interpolation='nearest')
        # 直方图名字
        plt.title("2D hist")
        # 图三
        plt.show()
    
    
    def backProjection():
        """直方图反射投影"""
        # 样本图片
        sample = cv.imread('images/test.jpg')
        # 目标片图片
        target = cv.imread('images/test2.jpg')
        sample_hsv = cv.cvtColor(sample, cv.COLOR_BGR2HSV)
        target_hsv = cv.cvtColor(target, cv.COLOR_BGR2HSV)
    
        # 图一
        cv.imshow("sample", sample)
        # 图二
        cv.imshow("target", target)
    
        # 获得样本图片直方图
        # [0,1]:用于计算直方图的通道,这里使用hsv计算直方图,所以就直接使用第一h和第二通道,即h和s通道;
        # None:是否使用mask,None 否
        # [32,32] bins 越多对每个像素细分的越厉害,会导致反响直方图的碎片化
        # [0,180,0,256]:hsv色彩空间中 h和s的取值范围,是固定的
        sample_hist = cv.calcHist([sample_hsv], [0, 1], None, [32, 32], [0, 180, 0, 256])
    
        # 规划样本图片直方图
        # sample_hist:输入的矩阵
        # sample_hist:归一化后的矩阵
        # 0:归一化后的矩阵的最小值
        # 255:归一化后的矩阵的最大值
        # cv.NORM_MINMAX:数组的数值被平移或缩放到一个指定的范围,线性归一化,一般较常用
        cv.normalize(sample_hist, sample_hist, 0, 255, cv.NORM_MINMAX)
        # 生成反射投影
        # target_hsv:目标图像hsv矩阵
        # [0,1]:用于计算直方图反射投影的通道,这里使用hsv计算直方图,所以就直接使用第一h和第二通道,即h和s通道;
        # [0,180,0,256]:hsv色彩空间中 h和s的取值范围,是固定的
        # 1:是否缩放大小,1不需要,0需要
        dst = cv.calcBackProject([target_hsv], [0, 1], sample_hist, [0, 180, 0, 256], 1)
        # 图四
        cv.imshow("bp", dst)
    
    
    src = cv.imread('images/test.jpg')
    # 2d 直方图计算和现实
    hist2d(src);
    # 直方图反射投影
    backProjection()
    
    # 等待用户操作
    cv.waitKey(0)
    # 释放所有窗口
    cv.destroyAllWindows()
    
    

    注意:直方图反向投影须在hsv色彩空间下进行


    image.png image.png image.png

    (十五) 模板匹配

    在整个图像区域发现与给定子图像匹配的区域,模板匹配的工作方式是在待检测图像上从左到右,从上到下计算模板图象与重叠子图像的匹配度,匹配度越大,两者越相同。
    OpenCV中的模板匹配

    CV_TM_SQDIFF 平方差匹配法:该方法采用平方差来进行匹配;最好的匹配值为0;匹配越差,匹配值越大。
    CV_TM_CCORR 相关匹配法:该方法采用乘法操作;数值越大表明匹配程度越好。
    CV_TM_CCOEFF 相关系数匹配法:1表示完美的匹配;-1表示最差的匹配。
    CV_TM_SQDIFF_NORMED 归一化平方差匹配法
    CV_TM_CCORR_NORMED 归一化相关匹配法
    CV_TM_CCOEFF_NORMED 归一化相关系数匹配法

    import cv2 as cv
    import numpy as np
    
    
    def template():
        # 模板图片
        tpl = cv.imread('images/template.jpg')
        # 目标图片
        target = cv.imread('images/template-target.jpg')
        cv.imshow('template', tpl)
        cv.imshow('target', target)
    
        methods = [cv.TM_SQDIFF_NORMED, cv.TM_CCORR_NORMED, cv.TM_CCOEFF_NORMED]
    
        # 获得模板的高宽
        th, tw = tpl.shape[:2]
        for md in methods:
            # 执行模板匹配
            # target:目标图片
            # tpl:模板图片
            # 匹配模式
            result = cv.matchTemplate(target, tpl, md)
            # 寻找矩阵(一维数组当作向量,用Mat定义) 中最小值和最大值的位置
            min_val, max_val, min_loc, max_loc = cv.minMaxLoc(result)
            if md == cv.TM_SQDIFF_NORMED:
                tl = min_loc
            else:
                tl = max_loc
    
            br = (tl[0] + tw, tl[1] + th)
            # 绘制矩形边框,将匹配区域标注出来
            # target:目标图像
            # tl:矩形定点
            # br:举行的宽高
            # (0,0,255):矩形边框颜色
            # 2:矩形边框大小
            cv.rectangle(target, tl, br, (0, 0, 255), 2)
            cv.imshow('match-' + np.str(md), target)
    
    
    template();
    
    cv.waitKey(0)
    cv.destroyAllWindows()
    
    
    模板图
    目标图
    匹配

    (十六)图像二值化

    图像中只有0和1,即1表示黑色,0表示白色
    图像二值化的方法:全局阈值,局部阈值。一般来说局部阈值要优于全局阈值。在OpenCV中图像二值化的方法有OTS,Triangle,自动与手动,衡量阈值方法是否是符合场景的,就是要看处理之后图像的信息是否丢失。

    import cv2 as cv
    import numpy as np
    
    def threshold(image):
        """图像二值化:全局阈值"""
        # 图像灰度化
        gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY)
        # 变为二值图像
        # gary:灰度图像
        # 0:阈值,如果选定了阈值方法,则这里不起作用
        ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_TRIANGLE)
        print(ret)
        cv.imshow("binary", binary)
    
    
    def local_threshold(image):
        """局部阈值"""
        # 图像灰度化
        gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY)
        # 变为二值图像
        binary = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 25, 10)
        cv.imshow("local_threshold", binary)
    
    # 此方法有错误
    def custom_threshold(image):
        """局部阈值"""
        gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
        cv.imshow("原来", gray)
        h, w = gray.shape[:2]
        m = np.reshape(gray, [1, w * h])  # 化为一维数组
        mean = m.sum() / (w * h)
        print("mean: ", mean)
        ret, binary = cv.threshold(gray, mean, 255, cv.THRESH_BINARY)
        cv.imshow("二值", binary)
    
    
    # 图像二值化 0白色 1黑色
    # 全局阈值
    def threshold_image(image):
        gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
        cv.imshow("原来", gray)
    
        ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)  # 大律法,全局自适应阈值 参数0可改为任意数字但不起作用
        print("阈值:%s" % ret)
        cv.imshow("OTSU", binary)
    
        ret, binary = cv.threshold(gray, 0, 255,
                                   cv.THRESH_BINARY | cv.THRESH_TRIANGLE)  # TRIANGLE法,,全局自适应阈值, 参数0可改为任意数字但不起作用,适用于单个波峰
        print("阈值:%s" % ret)
        cv.imshow("TRIANGLE", binary)
    
        ret, binary = cv.threshold(gray, 150, 255, cv.THRESH_BINARY)  # 自定义阈值为150,大于150的是白色 小于的是黑色
        print("阈值:%s" % ret)
        cv.imshow("自定义", binary)
    
        ret, binary = cv.threshold(gray, 150, 255, cv.THRESH_BINARY_INV)  # 自定义阈值为150,大于150的是黑色 小于的是白色
        print("阈值:%s" % ret)
        cv.imshow("自定义反色", binary)
    
        ret, binary = cv.threshold(gray, 150, 255, cv.THRESH_TRUNC)  # 截断 大于150的是改为150  小于150的保留
        print("阈值:%s" % ret)
        cv.imshow("截断1", binary)
    
        ret, binary = cv.threshold(gray, 150, 255, cv.THRESH_TOZERO)  # 截断 小于150的是改为150  大于150的保留
        print("阈值:%s" % ret)
        cv.imshow("截断2", binary)
    def big_img_binary(img):
        # 定义分割块的大小
        cw = 256
        ch = 256
        h,w = img.shape[:2]
        # 将图片转化为灰度图片
        gray = cv.cvtColor(img,cv.COLOR_RGB2GRAY)
        for row in range(0,h,ch):
            for col in range(0,w,cw):
                roi = gray[row:row+ch,col:col+cw]
                dst = cv.adaptiveThreshold(roi,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,127,20)
                gray[row:row+ch,col:col+cw]=dst
        cv.imshow("big image", gray)
    
    src = cv.imread('images/template.jpg')
    # threshold(src)
    # local_threshold(src)
    # threshold_image(src)
    # custom_threshold(src)
    big_img_binary(src)
    cv.waitKey(0)
    cv.destroyAllWindows()
    
    

    对于超大图象二值化一般都会进行分块。超大图象一般会分块以后使用全局二值化,或者使用局部二值化。并且应使用自适应阈值。

    全局阈值 局部阈值 自定义域值 大图象全局域值

    相关文章

      网友评论

          本文标题:Python视觉识别--OpenCV反射投影\模板匹配\图像二值

          本文链接:https://www.haomeiwen.com/subject/uixtiqtx.html