openCV-python模板匹配(旋转)

这篇具有很好参考价值的文章主要介绍了openCV-python模板匹配(旋转)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文将介绍使用OpenCV实现多角度模板匹配的详细步骤 + 代码。

背景介绍

熟悉OpenCV的朋友肯定都知道OpenCV自带的模板匹配matchTemplate方法是不支持旋转的,也就是说当目标和模板有角度差异时匹配常常会失败,可能目标只是轻微的旋转,匹配分数就会下降很多,导致匹配精度下降甚至匹配出错。本文介绍基于matchTemplate + 旋转 + 金字塔下采样实现多角度的模板匹配,返回匹配结果(坐标、角度)。

实现思路

【1】如何适应目标的角度变化?我们可以将模板旋转,从0~360°依次匹配找到最佳的匹配位置;

【2】如何提高匹配速度?使用金字塔下采样,将模板和待匹配图均缩小后匹配;加大匹配搜寻角度的步长,比如从每1°匹配一次改为每5°匹配一次等。

实现步骤

【1】旋转模板图像。旋转图像本身比较简单,下面是代码:

# 图片旋转函数
def ImageRotate(img, angle):   # img:输入图片;newIm:输出图片;angle:旋转角度(°)
    height, width = img.shape[:2]  # 输入(H,W,C),取 H,W 的值
    center = (width // 2, height // 2)  # 绕图片中心进行旋转
    M = cv.getRotationMatrix2D(center, angle, 1.0)
    image_rotation = cv.warpAffine(img, M, (width, height))
    return image_rotation

但需要注意,很多时候按照上面方法旋转时,会丢失模板信息产生黑边,这里是进行裁剪模板为圆形ROI

# 取圆形ROI区域函数:具体实现功能为输入原图,取原图最大可能的原型区域输出
def circle_tr(src):
    dst = np.zeros(src.shape, np.uint8)  # 感兴趣区域ROI
    mask = np.zeros(src.shape, dtype='uint8')  # 感兴趣区域ROI
    (h, w) = mask.shape[:2]
    (cX, cY) = (w // 2, h // 2)  # 是向下取整
    radius = int(min(h, w) / 2)
    cv.circle(mask, (cX, cY), radius, (255, 255, 255), -1)
    # 以下是copyTo的算法原理:
    # 先遍历每行每列(如果不是灰度图还需遍历通道,可以事先把mask图转为灰度图)
    for row in range(mask.shape[0]):
        for col in range(mask.shape[1]):
            # 如果掩图的像素不等于0,则dst(x,y) = scr(x,y)
            if mask[row, col] != 0:
                # dst_image和scr_Image一定要高宽通道数都相同,否则会报错
                dst[row, col] = src[row, col]
                # 如果掩图的像素等于0,则dst(x,y) = 0
            elif mask[row, col] == 0:
                dst[row, col] = 0
    return dst

【2】图像金字塔下采样。什么是图像金字塔?什么是上下采样?直接百度。

openCV-python模板匹配(旋转)

减小图像分辨率提高图像匹配速度,代码如下:

# 金字塔下采样
def ImagePyrDown(image,NumLevels):
    for i in range(NumLevels):
        image = cv.pyrDown(image)       #pyrDown下采样
    return image

【3】0~360°各角度匹配。旋转模板图像,依次调用matchTemplate在目标图中匹配,记录最佳匹配分数,以及对应的角度。旋转匹配代码:

# 旋转匹配函数(输入参数分别为模板图像、待匹配图像)
def RatationMatch(modelpicture, searchpicture):
    searchtmp = []
    modeltmp = []

    searchtmp = ImagePyrDown(searchpicture, 3)
    modeltmp = ImagePyrDown(modelpicture, 3)

    newIm = circle_tr(modeltmp)
    # 使用matchTemplate对原始灰度图像和图像模板进行匹配
    res = cv.matchTemplate(searchtmp, newIm, cv.TM_SQDIFF_NORMED)
    min_val, max_val, min_indx, max_indx = cv.minMaxLoc(res)
    location = min_indx
    temp = min_val
    angle = 0     # 当前旋转角度记录为0

    tic = time.time()
    # 以步长为5进行第一次粗循环匹配
    for i in range(-180, 181, 5):
        newIm = ImageRotate(modeltmp, i)
        newIm = circle_tr(newIm)
        res = cv.matchTemplate(searchtmp, newIm, cv.TM_SQDIFF_NORMED)
        min_val, max_val, min_indx, max_indx = cv.minMaxLoc(res)
        if min_val < temp:
            location = min_indx
            temp = min_val
            angle = i
    toc = time.time()
    print('第一次粗循环匹配所花时间为:' + str(1000*(toc - tic)) + 'ms')

    tic = time.time()
    # 在当前最优匹配角度周围10的区间以1为步长循环进行循环匹配计算
    for j in range(angle-5, angle+6):
        newIm = ImageRotate(modeltmp, j)
        newIm = circle_tr(newIm)
        res = cv.matchTemplate(searchtmp, newIm, cv.TM_SQDIFF_NORMED)
        min_val, max_val, min_indx, max_indx = cv.minMaxLoc(res)
        if min_val < temp:
            location = min_indx
            temp = min_val
            angle = j
    toc = time.time()
    print('在当前最优匹配角度周围10的区间以1为步长循环进行循环匹配所花时间为:' + str(1000*(toc - tic)) + 'ms')

    tic = time.time()
    # 在当前最优匹配角度周围2的区间以0.1为步长进行循环匹配计算
    k_angle = angle - 0.9
    for k in range(0, 19):
        k_angle = k_angle + 0.1
        newIm = ImageRotate(modeltmp, k_angle)
        newIm = circle_tr(newIm)
        res = cv.matchTemplate(searchtmp, newIm, cv.TM_SQDIFF_NORMED)
        min_val, max_val, min_indx, max_indx = cv.minMaxLoc(res)
        if min_val < temp:
            location = min_indx
            temp = min_val
            angle = k_angle
    toc = time.time()
    print('在当前最优匹配角度周围2的区间以0.1为步长进行循环匹配所花时间为:' + str(1000*(toc - tic)) + 'ms')

    # 用下采样前的图片来进行精匹配计算
    k_angle = angle - 0.1
    newIm = ImageRotate(modelpicture, k_angle)
    newIm = circle_tr(newIm)
    res = cv.matchTemplate(searchpicture, newIm, cv.TM_CCOEFF_NORMED)
    min_val, max_val, min_indx, max_indx = cv.minMaxLoc(res)
    location = max_indx
    temp = max_val
    angle = k_angle
    for k in range(1, 3):
        k_angle = k_angle + 0.1
        newIm = ImageRotate(modelpicture, k_angle)
        newIm = circle_tr(newIm)
        res = cv.matchTemplate(searchpicture, newIm, cv.TM_CCOEFF_NORMED)
        min_val, max_val, min_indx, max_indx = cv.minMaxLoc(res)
        if max_val > temp:
            location = max_indx
            temp = max_val
            angle = k_angle

    location_x = location[0] + 50
    location_y = location[1] + 50

    # 前面得到的旋转角度是匹配时模板图像旋转的角度,后面需要的角度值是待检测图像应该旋转的角度值,故需要做相反数变换
    angle = -angle

    match_point = {'angle': angle, 'point': (location_x, location_y)}
    return match_point

【4】标注匹配结果。根据模板图大小、匹配结果角度画出匹配框,代码如下:

# 画图
def draw_result(src, temp, match_point):
    cv.rectangle(src, match_point,
                  (match_point[0] + temp.shape[1], match_point[1] + temp.shape[0]),
                  (0, 255, 0), 2)
    cv.imshow('result', src)
    cv.waitKey()

【5】调用。对输入图像做预处理,并输出匹配到的结果,代码如下:

def get_realsense(src, temp):
    ModelImage = temp
    SearchImage = srcx
    ModelImage_edge = cv.GaussianBlur(ModelImage, (5, 5), 0)
    ModelImage_edge = cv.Canny(ModelImage_edge, 10, 200, apertureSize=3)
    SearchImage_edge = cv.GaussianBlur(SearchImage, (5, 5), 0)

    (h1, w1) = SearchImage_edge.shape[:2]
    SearchImage_edge = cv.Canny(SearchImage_edge, 10, 180, apertureSize=3)
    serch_ROIPart = SearchImage_edge[50:h1 - 50, 50:w1 - 50]  # 裁剪图像

    tic = time.time()
    match_points = RatationMatch(ModelImage_edge, serch_ROIPart)
    toc = time.time()
    print('匹配所花时间为:' + str(1000 * (toc - tic)) + 'ms')
    print('匹配的最优区域的起点坐标为:' + str(match_points['point']))
    print('相对旋转角度为:' + str(match_points['angle']))
    TmpImage_edge = ImageRotate(SearchImage_edge, match_points['angle'])
    cv.imshow("TmpImage_edge", TmpImage_edge)
    cv.waitKey()
    draw_result(SearchImage, ModelImage_edge, match_points['point'])
    return match_points

【6】举例演示。模板图从下图中截取并保存 template.png:

openCV-python模板匹配(旋转)
openCV-python模板匹配(旋转)

测试图像6张,匹配结果:

openCV-python模板匹配(旋转)
openCV-python模板匹配(旋转)
openCV-python模板匹配(旋转)
openCV-python模板匹配(旋转)
openCV-python模板匹配(旋转)
openCV-python模板匹配(旋转)
openCV-python模板匹配(旋转)
openCV-python模板匹配(旋转)
openCV-python模板匹配(旋转)
openCV-python模板匹配(旋转)
openCV-python模板匹配(旋转)
openCV-python模板匹配(旋转)

角度误差在正负1度左右。

后记

可以在此基础上添加匹配分数阈值和NMS实现多目标匹配。文章来源地址https://www.toymoban.com/news/detail-429526.html

到了这里,关于openCV-python模板匹配(旋转)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • OpenCV-Python学习(20)—— OpenCV 图像几何变换之图像旋转(cv.warpAffine、cv.getRotationMatrix2D、cv.rotate、np.rot90)

    1. 学习目标 学习旋转矩阵; 学习使用 OpenCV 的 cv.warpAffine 函数进行图片的旋转; 学习使用 OpenCV 的 cv.getRotationMatrix2D 来计算不同旋转中心的不同角度的 MAR 旋转变换矩阵; 学习使用 OpenCV 的 cv.rotate 进行特殊角度的旋转(90,180,270 度)。 2. 不同中心的旋转矩阵计算 2.1 图像

    2024年02月09日
    浏览(43)
  • opencv-python常用函数解析及参数介绍(五)——腐蚀与膨胀

    有些时候图片上会有一些划痕或者污渍,会影响图片的质量,假设我有一张写有“艾醒”的图片,但是有花花绿绿的划痕和污渍,这时我们就可以运用腐蚀与膨胀消除这些划痕和污渍 腐蚀的本质就是白吃黑,即数值较大的(较白的)吃掉数值较小的(较黑的) 我们可以用c

    2024年02月14日
    浏览(62)
  • OpenCV笔记:模板匹配 cv2.matchTemplate()、cv2.minMaxLoc() 与 绘制矩形 cv2.rectangle() 方法介绍

            模板匹配是用来在一副大图中搜寻查找模版图像位置的方法。绘制矩形是用来将模版图像的匹配结果展示出来的方法。         模板匹配实现简单(2~3行代码),计算效率高,不需要执行阈值化、边缘检测等操作来生成二值化图像。 但是: 如果输入图像中存

    2024年02月04日
    浏览(52)
  • OpenCV 笔记:cv2.matchTemplate() 单模板匹配和多模板匹配

            模板匹配是用来在一副大图中搜寻查找模版图像位置的方法。         模板匹配实现简单(2~3行代码),计算效率高,不需要执行阈值化、边缘检测等操作来生成二值化图像。 但是: 如果输入图像中存在变化的因素,包括旋转、缩放、视角变化等,模板匹配很容

    2024年02月05日
    浏览(47)
  • opencv#27模板匹配

         例如给定一张图片,如上图大矩阵所示,然后给定一张模板图像,如上图小矩阵。      我们在大图像中去搜索与小图像中相同的部分或者是最为相似的内容。比如我们在图像中以灰色区域给出一个与模板图像尺寸大小一致的区域,通过比较灰色区域中的内容与模板中

    2024年01月23日
    浏览(46)
  • Opencv——图像模板匹配

    什么是模板匹配呢? 看到这里大家是否会觉得很熟悉的感觉涌上心头!在人脸识别是不是也会看见 等等。 模板匹配可以看作是对象检测的一种非常基本的形式。使用模板匹配,我们可以使用包含要检测对象的“模板”来检测输入图像中的对象。 参数:(img: 原始图像、

    2024年02月16日
    浏览(43)
  • 用OpenCV进行模板匹配

    今天我们来研究一种传统图像处理领域中对象检测和跟踪不可或缺的方法——模板匹配,其主要目的是为了在图像上找到我们需要的图案,这听起来十分令人兴奋。 所以,事不宜迟,让我们直接开始吧! 模板匹配的算法的核心十分简单:它将模板与源图像中的每个部分进行

    2024年02月10日
    浏览(45)
  • OpenCV 模板匹配 matchTemplate

    模板匹配是一项在一副图像中寻找与另一幅模板图像最匹配(相似)部分的技术。模板匹配不是基于直方图的,而是通过在输入图像上滑动图像块(模板)同时对比相似度,来对模板和输入图像进行匹配的一种方法。 应用: (1)目标查找定位 (2)运动物体跟踪 image:待搜

    2024年02月04日
    浏览(66)
  • OpenCV(十九):模板匹配

    1.模板匹配:      OpenCV提供了一个模板匹配函数,用于在图像中寻找给定模板的匹配位置。 2.图像模板匹配函数matchTemplate  void matchTemplate( InputArray image, InputArray templ, OutputArray result, int method, InputArray mask = noArray() ); image:待模板匹配的原图像,图像数据类型为CV 8U和CV 32F两者中

    2024年02月09日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包