精华内容
下载资源
问答
  • 本代码是sift特征提取代码,sift特征可以用于人脸识别,图像检索 图像匹配 图像拼接,sift特征具有旋转不变形,尺度不变形,光照不变形等,此算法已广泛应用于人脸识别 图像检索 图像匹配 图像拼接的研究。...
  • 使用相关来匹配图像

    2019-05-10 09:40:15
    %使用相关来匹配图像 f=imread('Hurricane Andrew.tif'); subplot(2,2,1),imshow(f),title('多谱图像') w=imread('hurricane_mask.tif'); subplot(2,2,2),imshow(w),title('模板') g=dftcorr(f,w);%相关匹配 gs=...
    %使用相关来匹配图像
    f=imread('Hurricane Andrew.tif');
    subplot(2,2,1),imshow(f),title('多谱图像')
    
    w=imread('hurricane_mask.tif');
    subplot(2,2,2),imshow(w),title('模板')
    
    g=dftcorr(f,w);%相关匹配
    gs=gscale(g);
    subplot(2,2,3),imshow(gs),title('模板与图像相关')
    
    [I,J]=find(g==max(g(:)))%寻找最大值
    subplot(2,2,4),imshow(gs>254),title('最佳匹配位置')%显示最大值
    
    展开全文
  • 它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。 今天我们就是用python学习OpenCV。...

    本文仅做为本人学习记录。

    • 一、简介:

    OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。

    今天我们就是用python学习OpenCV。

    • 二、读取与显示
    import cv2 #导入opencv库
    #读取一张图片,地址不能带中文
    '''
    第二个参数,取值可为:
    cv2.IMREAD_COLOR:默认参数,读入一副彩色图片,忽略alpha通道 
    cv2.IMREAD_GRAYSCALE:读入灰度图片 
    cv2.IMREAD_UNCHANGED:读入完整图片,包括alpha通道(png有,jpg无)
    '''
    imgviewx=cv2.imread("0165_0024.jpg",cv2.IMREAD_COLOR)
    # imgviewx=cv2.imread("0165_0024.jpg")
    #显示图片,参数:(窗口标识字符串,imread读入的图像)
    cv2.imshow("img_window",imgviewx)
    #窗口等待任意键盘按键输入,0为一直等待,其他数字为毫秒数
    cv2.waitKey(0)
    #销毁窗口,退出程序
    cv2.destroyAllWindows()

    这里有一点需要注意,OpenCV中的默认颜色格式通常称为RGB,但实际上是BGR(字节是相反的)

    如果使用特征匹配等算法的时候就需要转换。如下:

    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    • 三 cv2.matchTemplate模板匹配和cv2.minMaxLoc()函数

    matchTemplate 函数原型:

    cv2.matchTemplate(image, templ, method, result=None, mask=None)
    # image:待搜索图像
    # templ:模板图像
    # result:匹配结果
    # method:计算匹配程度的方法
    

    关于匹配方法,使用不同的方法产生的结果的意义可能不太一样,有些返回的值越大表示匹配程度越好,而有些方法返回的值越小表示匹配程度越好。

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

    CV_TM_CCORR_NORMED 归一化相关匹配法

    CV_TM_CCOEFF_NORMED 归一化相关系数匹配法

    cv2.minMaxLoc() 函数原型

    cv2.minMaxLoc(src, mask=None)
    #src是一个矩阵。
    函数功能:假设有一个矩阵a,现在需要求这个矩阵的最小值,最大值,并得到最大值,最小值的索引。咋一看感觉很复杂,但使用这个cv2.minMaxLoc()函数就可全部解决。函数返回的四个值就是上述所要得到的。
    

    具体看个例子:

    import numpy as np
    import cv2
    a=np.array([[2,3,4,5],[5,67,8,9],[1,3,4,5]])
    print(a)
    min_val,max_val,min_indx,max_indx=cv2.minMaxLoc(a)
    
    print(min_val,max_val,min_indx,max_indx)
    
    输出结果:
    [[ 2 3 4 5]
    [ 5 67 8 9]
    [ 1 3 4 5]]
    1.0 67.0 (0, 2) (1, 1)
    说明这个矩阵a的最小值为1.0,索引为(0,2),最大值为67.0索引为(1,1)

    讲了这么多理论知识接下来我们来实战一下吧。

    import cv2 #导入opencv库
    # 图片不要使用中文
    img = cv2.imread('超级玛丽.jpg')
    template = cv2.imread('金币.jpg')
    h, w = template.shape[:2]  # rows->h, cols->w
    print('高:',h,"宽:",w)
    # 相关系数匹配方法:cv2.TM_CCOEFF
    res = cv2.matchTemplate(img, template, cv2.TM_CCOEFF)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
    
    left_top = max_loc  # 左上角
    right_bottom = (left_top[0] + w, left_top[1] + h)  # 右下角
    cv2.rectangle(img, left_top, right_bottom, 255, 2)  # 画出矩形位置
    
    #显示图片,参数:(窗口标识字符串,imread读入的图像)
    cv2.imshow("img_window",img)
    #窗口等待任意键盘按键输入,0为一直等待,其他数字为毫秒数
    cv2.waitKey(0)
    #销毁窗口,退出程序
    cv2.destroyAllWindows()

    自己运行一下吧。这里只能匹配到一个金币。下一节我们讲如何匹配全部金币。

    展开全文
  • python与opencv图像处理基础总结,模板匹配匹配的原理和几种常用算法,python调用opencv相关API的方法,图像二值化的处理,python调用opencv中的全局阈值函数和局部阈值函数,对图像图像阈值分割,实现图像二值化...

    一、模板匹配

    1. 匹配原理

    模板匹配是一种最原始、最基本的模式识别方法,研究某一特定对象物的图案位于图像的什么地方,进而识别对象物,这就是一个匹配问题。它是图像处理中最基本、最常用的匹配方法。模板匹配具有自身的局限性,主要表现在它只能进行平行移动,若原图像中的匹配目标发生旋转或大小变化,该算法无效。

    • 模板匹配就是在整个图像区域发现与给定子图像匹配的小块区域
    • 所以模板匹配首先需要一个模板图像(给定的子图像)
    • 另外需要一个待检测图像—源图像
    • 在待检测图像上,从左到右,从上向下,计算模板图像与重叠子图像的匹配度,匹配度越高,两者相同的可能性越大。

    2. 匹配算法

    在这里插入图片描述

    • TM_SQDIFF是平方差匹配;TM_SQDIFF_NORMED是标准平方差匹配。利用平方差来进行匹配,最好匹配为0;匹配越差,匹配值越大。
    • TM_CCORR是相关性匹配;TM_CCORR_NORMED是标准相关性匹配。采用模板和图像间的乘法操作,数越大表示匹配程度较高,0表示最坏的匹配效果。
    • TM_CCOEFF是相关性系数匹配;TM_CCOEFF_NORMED是标准相关性系数匹配。将模版对其均值的相对值与图像对其均值的相关值进行匹配,1表示完美匹配,-1表示糟糕的匹配,0表示没有任何相关性(随机序列)。

    从简单的测量(平方差)到更复杂的测量(相关系数),可获得越来越准确的匹配(同时也意味着越来越大的计算代价)。

    3. opencv相关API

    opencv的目标匹配函数

    cv2.matchTemplate(image, templ, method, result=None, mask=None) -> result
    
    mage参数表示待检测源图像,必须是8位整数或32位浮点。
    templ参数表示模板图像,必须不大于源图像并具有相同的数据类型。
    method参数表示计算匹配程度的方法。
    result参数表示匹配结果图像,必须是单通道32位浮点。如果image的尺寸为W x H,templ的尺寸为w x h,则result的尺寸为(W-w+1)x(H-h+1)

    opencv的函数minMaxLoc:在给定的矩阵中寻找最大和最小值,并给出它们的位置。 该功能不适用于多通道阵列,如果需要在所有通道中查找最小或最大元素,要先将阵列重新解释为单通道。

    minMaxLoc(src, mask=None) -> minVal, maxVal, minLoc, maxLoc
    
    src参数表示输入单通道图像
    mask参数表示用于选择子数组的可选掩码
    minVal参数表示返回的最小值,如果不需要,则使用NULL。
    maxVal参数表示返回的最大值,如果不需要,则使用NULL。
    minLoc参数表示返回的最小位置的指针(在2D情况下); 如果不需要,则使用NULL。
    maxLoc参数表示返回的最大位置的指针(在2D情况下); 如果不需要,则使用NULL。
    

    opencv的函数rectangle用于绘制矩形

     cv2.rectangle(img, pt1, pt2, color, thickness=None, lineType=None, shift=None) -> img
     
    img参数表示源图像
    pt1参数表示矩形的一个顶点(左上)
    pt2参数表示与pt1相对的对角线上的另一个顶点(右下)
    color参数表示矩形线条颜色 (RGB) 或亮度(灰度图像)
    thickness参数表示组成矩形的线条的粗细程度,取负值时(如 CV_FILLED)函数绘制填充了色彩的矩形。
    lineType参数表示线条的类型
    shift参数表示坐标点的小数点位数
    

    代码如下:

    import cv2 as cv
    import numpy as np
    
    
    def template_matching():
        sample = cv.imread(r'./test/031.png')    # 模板图像
        target = cv.imread(r'./test/030.jpg')    # 待检测图像
        cv.imshow('sample', sample)
        cv.imshow('target', target)
        # 三种模板匹配算法
        methods = [cv.TM_SQDIFF_NORMED, cv.TM_CCORR_NORMED, cv.TM_CCOEFF_NORMED]
        height, width = sample.shape[:2]   # 模板图像的高 宽
        for method in methods:
            print(method)
            result = cv.matchTemplate(image=target, templ=sample, method=method)  # 计算那个区域匹配最好
            # 在匹配的结果中寻找   最小值  最大值及最小、最大值的位置
            min_val, max_val, min_loc, max_loc = cv.minMaxLoc(result)
            if method == cv.TM_SQDIFF_NORMED:   # 如果是标准平方差匹配  取最小值位置
                left_top = min_loc
            else:
                left_top = max_loc
            right_bottom = (left_top[0] + width, left_top[1] + height)  # 加上宽  高
            # 匹配到最佳位置    画小矩形
            cv.rectangle(img=target, pt1=left_top, pt2=right_bottom, color=(0, 0, 255), thickness=2)
            cv.imshow('match-' + np.str(method), target)
    
    template_matching()
    cv.waitKey(0)
    cv.destroyAllWindows()
    

    运行效果如下:

    模板图像

    在这里插入图片描述
    匹配结果

    在这里插入图片描述

    二、图像二值化

    在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓。

    该函数的阈值操作属于像素级的操作,在灰度图中,每个像素都对应一个灰度值(0~255,0黑、255白),我们将阈值函数 threshold() 应用于图像,图像的灰度值与阈值进行比较,从而实现二值化处理,目的是滤除太大或太小值像素、消除噪声,从而从灰度图中获取二值图像(将图像的灰度值设置为0或255),实现增强整个图像呈现更为明显的黑白效果,同时也大大减少了数据量。

    import cv2 as cv
    import numpy as np
    
    
    # 全局
    def threshold_image(image):
        gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
        ret, binary = cv.threshold(src=gray, thresh=0, maxval=255, type=cv.THRESH_BINARY | cv.THRESH_OTSU)
        # ret, binary = cv.threshold(src=gray, thresh=0, maxval=255, type=cv.THRESH_BINARY | cv.THRESH_TRIANGLE)
        # ret, binary = cv.threshold(src=gray, thresh=115, maxval=255, type=cv.THRESH_BINARY)
        # ret, binary = cv.threshold(src=gray, thresh=127, maxval=255, type=cv.THRESH_BINARY_INV)  # 相反
        # ret, binary = cv.threshold(src=gray, thresh=127, maxval=255, type=cv.THRESH_TRUNC)
        # ret, binary = cv.threshold(src=gray, thresh=130, maxval=255, type=cv.THRESH_TOZERO)
        print(f'threshold value:{ret}')    # 阈值    看图像信息丢失情况
        cv.imshow('threshold binary image', binary)
    
    
    # 局部  自适应阈值
    def local_image(image):
        gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
        # dst = cv.adaptiveThreshold(src=gray, maxValue=255, adaptiveMethod=cv.ADAPTIVE_THRESH_MEAN_C,
        #                      thresholdType=cv.THRESH_BINARY, blockSize=25, C=10)     # blockSize必须是奇数  C 常量
        dst = cv.adaptiveThreshold(src=gray, maxValue=255, adaptiveMethod=cv.ADAPTIVE_THRESH_GAUSSIAN_C,
                                   thresholdType=cv.THRESH_BINARY, blockSize=25, C=10)  # blockSize必须是奇数  C 常量
    
        cv.imshow('local binary image', dst)
    
    # 自定义   均值作为阈值
    def custom_image(image):
        gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
        h, w = gray.shape[:2]
        m = np.reshape(gray, [1, h * w])
        mean = m.sum() / (w * h)
        print(f'mean:{mean}')
        ret, binary = cv.threshold(gray, mean, 255, cv.THRESH_BINARY)
        cv.imshow('custom binary image', binary)
    
    
    
    src = cv.imread(r'./test/014.png')
    cv.imshow('input image', src)
    threshold_image(src)
    local_image(src)
    custom_image(src)
    cv.waitKey(0)
    cv.destroyAllWindows()
    

    1. 全局阈值函数

    cv2.threshold(src, thresh, maxval, type, dst=None)
    
    src - 输入图像(多通道,8位或32位浮点)
    thresh - 阈值
    maxval - 最大值
    type - 阈值类型
    dst - 输出图像(与src相同大小和类型以及相同通道数的数组/图像)
    

    阈值类型

    • cv2.THRESH_BINARY 二值阈值化 —— 像素值大于阈值的设为最大值,小于阈值的设为最小值。
    • cv2.THRESH_BINARY_INV 反向二值阈值化 —— 像素值大于阈值的设为最小值,小于阈值的设为最大值。
    • cv2.THRESH_TRUNC 截断阈值化 —— 像素值大于阈值的设为阈值,小于阈值的保持原来的像素值。
    • cv2.THRESH_TOZERO 超过阈值被置0 —— 像素值大于阈值的置为0,小于阈值的保持原来的像素值。
    • cv2.THRESH_TOZERO_INV 像素值大于阈值的保持原来的像素值,小于阈值的置为0。

    在这里插入图片描述
    这些函数都有两个返回值,第一个返回值为使用的阈值,第二个就是阈值化后的图像。

    最大类间方差法

    对于图像二值化的简单阈值法,我们需要自己提供一个阈值,而最大类间方差法可以根据图像特性,选择最佳的阈值,故它也被认为是图像分割中阈值选取的最佳算法,计算简单,不受图像亮度和对比度的影响。按照最大类间方差法求得的阈值进行图像二值化分割后,前景与背景图像的类间方差最大。

    它是按图像的灰度特性,将图像分成背景和前景两部分。因方差是灰度分布均匀性的一种度量,背景和前景之间的类间方差越大,说明构成图像的两部分的差别越大,当部分前景错分为背景或部分背景错分为前景都会导致两部分差别变小。因此,使类间方差最大的分割意味着错分概率最小。

    应用:是求图像全局阈值的最佳方法,应用不言而喻,适用于大部分需要求图像全局阈值的场合。

    优点:计算简单快速,不受图像亮度和对比度的影响。

    缺点:对图像噪声敏感;只能针对单一目标分割;当目标和背景大小比例悬殊、类间方差函数可能呈现双峰或者多峰,这个时候效果不好。

    代码如下:

    import cv2 as cv
    
    
    # 全局
    def threshold_image(image):
        gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
        ret, binary = cv.threshold(src=gray, thresh=0, maxval=255, type=cv.THRESH_BINARY | cv.THRESH_OTSU)
        print(f'threshold value:{ret}')    # 阈值    看图像信息丢失情况
        cv.imshow('threshold binary image', binary)
    
    
    # 局部  自适应阈值
    def local_image(image):
        gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    
        dst = cv.adaptiveThreshold(src=gray, maxValue=255, adaptiveMethod=cv.ADAPTIVE_THRESH_GAUSSIAN_C,
                                   thresholdType=cv.THRESH_BINARY, blockSize=25, C=10)  # blockSize必须是奇数  C 常量
    
        cv.imshow('local binary image', dst)
    
    
    src = cv.imread(r'./test/014.png')
    cv.imshow('input image', src)
    threshold_image(src)
    local_image(src)
    cv.waitKey(0)
    cv.destroyAllWindows()
    

    运行效果如下:

    在这里插入图片描述

    2. 局部阈值函数

    全局阈值法对于某些光照不均的图像,这种全局阈值分割的效果不好。
    而利用局部阈值法,根据图像上的每一个小区域计算与其对应的阀值。因此在同一幅图像上的不同区域采用的是不同的阀值,从而使我们在亮度不同的情况下得到更好的结果。

    cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None): 
    
    src - 输入图像(8位单通道图像)
    maxValue - THRESH_BINARY 和 THRESH_BINARY_INV 的最大值
    adaptiveMethod - 自适应阈值算法,平均 (ADAPTIVE_THRESH_MEAN_C)或高斯(ADAPTIVE_THRESH_GAUSSIAN_C)
    thresholdType - 阈值类型,必须为THRESH_BINARY或THRESH_BINARY_INV的阈值类型
    blockSize - 块大小(奇数且大于1)
    C - 常量,从平均值或加权平均值中减去的数
    

    代码如下:

    import cv2 as cv
    import numpy as np
    
    
    # 全局
    def threshold_image(image):
        gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
        ret, binary = cv.threshold(src=gray, thresh=0, maxval=255, type=cv.THRESH_BINARY | cv.THRESH_OTSU)
        print(f'threshold value:{ret}')    # 阈值    看图像信息丢失情况
        cv.imshow('threshold binary image', binary)
    
    
    # 局部  自适应阈值
    def local_image(image):
        gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
        dst = cv.adaptiveThreshold(src=gray, maxValue=255, adaptiveMethod=cv.ADAPTIVE_THRESH_GAUSSIAN_C,
                                   thresholdType=cv.THRESH_BINARY, blockSize=25, C=10)  # blockSize必须是奇数  C 常量
    
        cv.imshow('local binary image', dst)
    
    
    src = cv.imread(r'./test/032.png')
    cv.imshow('input image', src)
    threshold_image(src)
    local_image(src)
    cv.waitKey(0)
    cv.destroyAllWindows()
    

    运行效果如下:
    在这里插入图片描述

    作者:叶庭云
    CSDN:https://blog.csdn.net/fyfugoyfa
    本文仅用于交流学习,未经作者允许,禁止转载,更勿做其他用途,违者必究。
    文章对你有所帮助的话,欢迎给个赞或者 star 呀,你的支持是对作者最大的鼓励,不足之处可以在评论区多多指正,交流学习呀。

    展开全文
  • opencv自带的stitching速度很慢, 其中一个最大的原因是每一张图都要和其它的图去匹配,如果有10张图...Stitch读入图像不用按照从左到右的顺序,拼接结果和运行时间都是一样的。 我们拍摄全景图的时候都是从左到右,...

    opencv自带的stitching速度很慢, 其中一个最大的原因是每一张图都要和其它的图去匹配,如果有10张图,除去自身不用匹配外,要匹配 10X(10-1) = 90 次。10张532*300图拼接耗时14s左右,还姑且能忍受。可是100张图要匹配9900次。耗时不是简单的线性增长。
    Stitch读入图像不用按照从左到右的顺序,拼接结果和运行时间都是一样的。

    我们拍摄全景图的时候都是从左到右,或者从右到左,前后两张图一般有部分重合。所以一个节省时间的好办法就是我们这里只对前后两张图匹配,然后连成一串。即用串联匹配代替原匹配。
    一些修改:
    1.把匹配方法换成串联匹配

    2.把费时的光束平差法改成"ray";//射线发散误差方法

    3.再把费时的曝光补偿改成ExposureCompensator::GAIN;//增益法

    4.接着把也费时的寻找接缝线改成"voronoi"; //逐点法

    #include "opencv2/core/core.hpp"
    #include "highgui.h"
    #include "opencv2/imgproc/imgproc.hpp"
    #include "opencv2/features2d/features2d.hpp"
    #include "opencv2/highgui/highgui.hpp"
    #include "opencv2/nonfree/nonfree.hpp"
    #include "opencv2/legacy/legacy.hpp"
    #include "cvaux.h" //必须引此头文件
    #include "opencv2/stitching/detail/autocalib.hpp"
    #include "opencv2/stitching/detail/blenders.hpp"
    #include "opencv2/stitching/detail/camera.hpp"
    #include "opencv2/stitching/detail/exposure_compensate.hpp"
    #include "opencv2/stitching/detail/matchers.hpp"
    #include "opencv2/stitching/detail/motion_estimators.hpp"
    #include "opencv2/stitching/detail/seam_finders.hpp"
    #include "opencv2/stitching/detail/util.hpp"
    #include "opencv2/stitching/detail/warpers.hpp"
    #include "opencv2/stitching/warpers.hpp"
    
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <iomanip>
    #include<vector>
    using namespace cv;
    using namespace std;
    using namespace detail;
    
    void f2_matcher(vector<ImageFeatures> &features, vector<MatchesInfo> &f2_matches)
    {
    
    	//vector<MatchesInfo> f2_matches;    //特征匹配
    	BestOf2NearestMatcher matcher(false, 0.3f, 6, 6);    //定义特征匹配器,2NN方法
    	matcher(features, f2_matches);    //进行特征匹配
    
    
    }
    
    
    
    void i_matcher(vector<ImageFeatures> &features, vector<MatchesInfo> &pairwise_matches)
    {
    	int num_images=features.size ();
    	//1。串联匹配
    	vector<vector<MatchesInfo> > f2_2;//f2_2[i] 表示 i 和 i+1 的匹配关系(0 开头,比图像数小 1)
        for (int i = 1; i < num_images; ++i)
        {
    		vector<ImageFeatures> f2;
    		vector<MatchesInfo> m2;
    		f2.push_back (features[i-1]);
    		f2.push_back (features[i]);
    		f2_matcher(f2,m2);
    		f2_2.push_back(m2);
    
    	}
    
    
    	//2。把串联匹配 ----按opencv stitching 拼接的匹配关系组在一起
    	MatchesInfo f;//大小: n x n (n个图)
        for (int i = 0; i < num_images; ++i)
        {
    		for (int j = 0; j < num_images; ++j)
    		{
    			//cout<<"i,j:"<<i<<","<<j<<endl;
    			if(i==j)//自身不用匹配
    			{
    				f.src_img_idx = -1;
    				f.dst_img_idx = -1;
    				f.num_inliers = 0;
    				f.confidence = 0;
    				pairwise_matches.push_back (f);
    			}else if(i+1==j)//相连(顺)
    			{
    				pairwise_matches.push_back (f2_2[i][1]);
    				//修改匹配关系
    				pairwise_matches[pairwise_matches.size ()-1].src_img_idx =i;
    				pairwise_matches[pairwise_matches.size ()-1].dst_img_idx =j;
    			}else if(j+1==i)//相连(倒)
    			{
    				pairwise_matches.push_back (f2_2[j][2]);
    				//修改匹配关系
    				pairwise_matches[pairwise_matches.size ()-1].src_img_idx =i;
    				pairwise_matches[pairwise_matches.size ()-1].dst_img_idx =j;
    			}else//其它略过
    			{
    				f.src_img_idx = -1;
    				f.dst_img_idx = -1;
    				f.num_inliers = 0;
    				f.confidence = 0;
    				pairwise_matches.push_back (f);
    			}
    			//cout<<"size:"<<pairwise_matches.size ()<<endl;
    
    		}
    	}
    }
    
    
    int main(int argc, char** argv)
    {
    	vector<Mat> imgs;    //输入图像
    	Mat img;
    	char temp[100];
        double ge[100];//100张图的特征点个数
        for (int i = 1; i<= 100; i++)
        {
        sprintf(temp, "D:\\低分辨率截图重命名\\%d.jpg", i);// 将图片以数字命名:例如1.jpg 2.jpg等
        img = imread(temp);
        imgs.push_back(img);
    	}
        int num_images =100;    //图像数量
    	vector<ImageFeatures> features(num_images);    //表示图像特征
    
        Point2f point;
    	KeyPoint kp;
    	float temp1 = 0, temp2 = 0;
    	char ptsname[100];
    	char descname[100];
    	ifstream g("D:\\特征\\特征点个数.txt");//将100张图的特征点个数导入数组
        assert(g.is_open());
    	for(int i=1;i<=100;i++)
    {
        g>>ge[i-1];
    }
        g.close();
    	for(int i=1;i<=100;i++)
    {
        sprintf(ptsname, "D:\\特征\\pts%d.txt",i); //格式化输出文件名
        ifstream infile(ptsname);
    	assert(infile.is_open());   //若失败,则输出错误消息,并终止程序运行
    	for (int a = 0; !infile.eof(); a++)
    	{
    		infile >> temp1 >> temp2;
    		point.x = temp1;
    		point.y = temp2;
    		kp = KeyPoint(point, 1.f);
    		features[i-1].keypoints.push_back(kp);
    	}
    	infile.close();
    	//infile.clear();
    
    	sprintf(descname, "D:\\特征\\desc%d.txt",i); //格式化输出文件名
        ifstream des(descname);
    	assert(des.is_open());   //若失败,则输出错误消息,并终止程序运行
        cout<<ge[i-1];
    	features[i-1].descriptors = Mat::zeros(ge[i-1], 256, CV_32FC1);//同理features[0].descriptors
    	for (int k = 0; k <ge[i-1]; k++)
    	{
    		for (int j = 0; j < 256; j++)
    		{
    			des >> features[i-1].descriptors.at<float>(k, j);
    		}
    			}
    	des.close();
    	//des.clear();
    }
    	vector<MatchesInfo> pairwise_matches;    //表示特征匹配信息变量
    	BestOf2NearestMatcher matcher(false, 0.3f, 6, 6);    //定义特征匹配器,2NN方法
    	//matcher(features, pairwise_matches);    //进行特征匹配
        i_matcher(features, pairwise_matches);//这里用我们自己的匹配代替
    cout<<"96行";
    
    	HomographyBasedEstimator estimator;    //定义参数评估器
    	vector<CameraParams> cameras;    //表示相机参数
    	estimator(features, pairwise_matches, cameras);    //进行相机参数评估
    cout<<'1';
    	for (size_t i = 0; i < cameras.size(); ++i)    //转换相机旋转参数的数据类型
    	{
    		Mat R;
    		cameras[i].R.convertTo(R, CV_32F);
    		cameras[i].R = R;
    	}
    
    	Ptr<detail::BundleAdjusterBase> adjuster;    //光束平差法,精确相机参数
    	//adjuster = new detail::BundleAdjusterReproj();    //重映射误差方法
    	adjuster = new detail::BundleAdjusterRay();    //射线发散误差方法
    cout<<"96行";
    	adjuster->setConfThresh(1);    //设置匹配置信度,该值设为1
    	(*adjuster)(features, pairwise_matches, cameras);    //精确评估相机参数
    cout<<"96行";
    	vector<Mat> rmats;
    	for (size_t i = 0; i < cameras.size(); ++i)    //复制相机的旋转参数
    		rmats.push_back(cameras[i].R.clone());
    	waveCorrect(rmats, WAVE_CORRECT_HORIZ);    //进行波形校正
    	for (size_t i = 0; i < cameras.size(); ++i)    //相机参数赋值
    		cameras[i].R = rmats[i];
    	rmats.clear();    //清变量
    
    	vector<Point> corners(num_images);    //表示映射变换后图像的左上角坐标
    	vector<Mat> masks_warped(num_images);    //表示映射变换后的图像掩码
    	vector<Mat> images_warped(num_images);    //表示映射变换后的图像
    	vector<Size> sizes(num_images);    //表示映射变换后的图像尺寸
    	vector<Mat> masks(num_images);    //表示源图的掩码
    cout<<"129行";
    	for (int i = 0; i < num_images; ++i)    //初始化源图的掩码
    	{
    		masks[i].create(imgs[i].size(), CV_8U);    //定义尺寸大小
    		masks[i].setTo(Scalar::all(255));    //全部赋值为255,表示源图的所有区域都使用
    	}
    
    	Ptr<WarperCreator> warper_creator;    //定义图像映射变换创造器
    	warper_creator = new cv::PlaneWarper();    //平面投影
    	//warper_creator = new cv::CylindricalWarper();    //柱面投影
    	//warper_creator = new cv::SphericalWarper();    //球面投影
    	//warper_creator = new cv::FisheyeWarper();    //鱼眼投影
    	//warper_creator = new cv::StereographicWarper();    //立方体投影
    
    	//定义图像映射变换器,设置映射的尺度为相机的焦距,所有相机的焦距都相同
    	Ptr<RotationWarper> warper = warper_creator->create(static_cast<float>(cameras[0].focal));
    	for (int i = 0; i < num_images; ++i)
    	{
    		Mat_<float> K;
    		cameras[i].K().convertTo(K, CV_32F);    //转换相机内参数的数据类型
    		//对当前图像镜像投影变换,得到变换后的图像以及该图像的左上角坐标
    		corners[i] = warper->warp(imgs[i], K, cameras[i].R, INTER_LINEAR, BORDER_REFLECT, images_warped[i]);
    		sizes[i] = images_warped[i].size();    //得到尺寸
    		//得到变换后的图像掩码
    		warper->warp(masks[i], K, cameras[i].R, INTER_NEAREST, BORDER_CONSTANT, masks_warped[i]);
    	}
    
    	imgs.clear();    //清变量
    	masks.clear();
    
    	//创建曝光补偿器,应用增益补偿方法
    	Ptr<ExposureCompensator> compensator =
    		ExposureCompensator::createDefault(ExposureCompensator::GAIN);
    	compensator->feed(corners, images_warped, masks_warped);    //得到曝光补偿器
    	for (int i = 0; i < num_images; ++i)    //应用曝光补偿器,对图像进行曝光补偿
    	{
    		compensator->apply(i, corners[i], images_warped[i], masks_warped[i]);
    	}
    
    	//在后面,我们还需要用到映射变换图的掩码masks_warped,因此这里为该变量添加一个副本masks_seam
    	vector<Mat> masks_seam(num_images);
    	for (int i = 0; i < num_images; i++)
    		masks_warped[i].copyTo(masks_seam[i]);
    
    	Ptr<SeamFinder> seam_finder;    //定义接缝线寻找器
       //seam_finder = new NoSeamFinder();    //无需寻找接缝线
       seam_finder = new VoronoiSeamFinder();    //逐点法
       //seam_finder = new DpSeamFinder(DpSeamFinder::COLOR);    //动态规范法
       //seam_finder = new DpSeamFinder(DpSeamFinder::COLOR_GRAD);
       //图割法
       //seam_finder = new GraphCutSeamFinder(GraphCutSeamFinder::COST_COLOR);
    	//seam_finder = new GraphCutSeamFinder(GraphCutSeamFinder::COST_COLOR_GRAD);
    
    	vector<Mat> images_warped_f(num_images);
    	for (int i = 0; i < num_images; ++i)    //图像数据类型转换
    		images_warped[i].convertTo(images_warped_f[i], CV_32F);
    
    	images_warped.clear();    //清内存
    
    	//得到接缝线的掩码图像masks_seam
    	seam_finder->find(images_warped_f, corners, masks_seam);
    cout<<"190行";
    	vector<Mat> images_warped_s(num_images);
    	Ptr<Blender> blender;    //定义图像融合器
    
    	//blender = Blender::createDefault(Blender::NO, false);    //简单融合方法
    	//羽化融合方法
    	//blender = Blender::createDefault(Blender::FEATHER, false);
    	//FeatherBlender* fb = dynamic_cast<FeatherBlender*>(static_cast<Blender*>(blender));
    	//fb->setSharpness(0.005);    //设置羽化锐度
    
    	blender = Blender::createDefault(Blender::MULTI_BAND, false);    //多频段融合
    	MultiBandBlender* mb = dynamic_cast<MultiBandBlender*>(static_cast<Blender*>(blender));
    	mb->setNumBands(8);   //设置频段数,即金字塔层数
    
    	blender->prepare(corners, sizes);    //生成全景图像区域
    
    	//在融合的时候,最重要的是在接缝线两侧进行处理,而上一步在寻找接缝线后得到的掩码的边界就是接缝线处,因此我们还需要在接缝线两侧开辟一块区域用于融合处理,这一处理过程对羽化方法尤为关键
    	//应用膨胀算法缩小掩码面积
    	vector<Mat> dilate_img(num_images);
    	Mat element = getStructuringElement(MORPH_RECT, Size(20, 20));    //定义结构元素
    	for (int k = 0; k < num_images; k++)
    	{
    		images_warped_f[k].convertTo(images_warped_s[k], CV_16S);    //改变数据类型
    		dilate(masks_seam[k], masks_seam[k], element);    //膨胀运算
    		//映射变换图的掩码和膨胀后的掩码相“与”,从而使扩展的区域仅仅限于接缝线两侧,其他边界处不受影响
    		masks_seam[k] = masks_seam[k] & masks_warped[k];
    		blender->feed(images_warped_s[k], masks_seam[k], corners[k]);    //初始化数据
    	}
    
    	masks_seam.clear();    //清内存
    	images_warped_s.clear();
    	masks_warped.clear();
    	images_warped_f.clear();
    
    	Mat result, result_mask;
    	//完成融合操作,得到全景图像result和它的掩码result_mask
    	blender->blend(result, result_mask);
    
    	imwrite("pano.jpg", result);    //存储全景图像
    
    	return 0;
    
    }
    
    
    展开全文
  • Photoshop CS5 轻松匹配图像颜色

    千次阅读 2011-11-30 23:27:50
    匹配颜色命令能够使一幅图像的色调与另一幅图像的色调自动匹配,这样就可以使不同图片拼合时达到色调统一,或者对照其他图像的色调修改自己的图像色调。 【实例1】 操作步骤: 1、 同时打开两个“匹配1A”和...
  • 形状上下文matlab 怎么建立匹配模型数据库?想要通过形状上下文来识别一系列图像,用形状上下文,可能实现嘛?
  • OpenCV匹配图像的特征向量

    千次阅读 2014-12-28 22:36:51
    匹配两幅图像的特征向量。 使用函数  drawMatches  来绘制检测到的匹配点. #include "opencv2/core/core.hpp" #include "opencv2/features2d/features2d.hpp" #include "opencv2/highgui/highgui....
  • 因此,图像增强问题看成是将输入图像转化为在训练照片集中嵌入所需特征的增强图像,采用类似于CycleGAN的two-way GAN结构来解决这个问题,由于GAN的训练具有不稳定性,我们做了一些改进: 扩展了U-Net,加入全局...
  • 单应性矩阵算过后的投影点的偏移量 scene_corners[0],就是在匹配图像中的点的位置,因为效果图像相当于增加了一个待匹配图像的宽度,所以每一个点都要加上 Point2f( img_1.cols, 0) 两个重要函数的介绍: ...
  • 2、得到识别的物体矩形坐标后,通过下面方法提取感兴趣区域图像 /// &lt;summary&gt; /// 安装矩形裁剪指定图片 /// &lt;/summary&gt; /// &lt;param name="est"&gt;&...
  • 大致看了一下sift和surf算法,发现surf来匹配图像效率高一点,但是surf只匹配出两幅图对应的特征点,那基于什么情况可以判断两幅图匹配成功了呢? 我在opencv论坛问过,说是匹配之后会建立一个矩阵: if( !...
  • 图像匹配算法介绍图像匹配算法介绍图像匹配算法介绍图像匹配算法介绍图像匹配算法介绍图像匹配算法介绍
  • 图像处理之图像匹配

    千次阅读 2019-08-07 22:19:52
    该说图像匹配了,图像匹配在图片处理中的作用举重若轻,今天就带大家入门图像匹配,简单介绍一下基础的图像匹配吧。 何为图像匹配呢?在原图片中扣出一块区域,然后通过...**1.**通过欧式距离来匹配图像。 将所有像...
  • 文章目录一、理论介绍二、代码 ...用T表示模板图像,I表示待匹配图像,切模板图像的宽为w高为h,用R表示匹配结果,匹配过程(图示如上): 通过 滑动, 我们的意思是图像块一次移动一个像素 (从左往右,从上往下)....
  • 图像匹配

    2018-12-29 11:22:06
    图像配准之后,模板图像和被检测图像之间的各种特征就能对应起来,还要继续提取缺陷像素点,即找到模板图与待检图之间的区别。这时候的做法成为图像匹配,常见的匹配方法有相关法和差影法。...
  • 图像匹配图像配准、图像校正

    热门讨论 2011-12-06 20:07:02
    该文档,详细描述了,图像处理中经常遇到的三个概念图像匹配图像配准、及图像校正,能有效地帮助同学们加深对这三个概念的理解和辨别,以便选择正确有效地方法进行图像处理。
  • 什么是图像匹配图像匹配,是指以模板图像作为标准目标,在待匹配图像中寻找与标准目标相似性高的单个或多个目标,根据图像信息如:灰度,梯度等计算不同位置不同角度情况下的相似性,确定目标在图像中的位置以及相...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 12,438
精华内容 4,975
关键字:

匹配图像