python图像金字塔模板匹配

564 阅读1分钟

 

本文主要针对图像金字塔进行模版匹配,可以匹配到一幅图像中多个目标。

一、主要流程:

  1. 主要对模板构建图像金字塔
  2. 利用opencv对1中得到模板图像,进行模版匹配
  3. 对2中得到的匹配框进行nms处理
  4. 对3中符合要求匹配框进行nms处理,最后的检测框即为符合的匹配框

二、nms处理代码

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
Descripttion: 
version: 1.0
Author:
Date: 2020-09-21 17:29:05
LastEditors: 
LastEditTime: 2020-09-29 16:55:43
Software:: Visual Studio Code
FilePath: nms.py
'''
import numpy as np


def py_cpu_nms(dets, thresh):
    x1 = dets[:, 0]
    y1 = dets[:, 1]
    x2 = dets[:, 2]
    y2 = dets[:, 3]
    scores = dets[:, 4]

    areas = (x2 - x1 + 1) * (y2 - y1 + 1)
    order = scores.argsort()[::-1]

    keep = []
    while order.size > 0:
        i = order[0]
        keep.append(i)
        xx1 = np.maximum(x1[i], x1[order[1:]])
        yy1 = np.maximum(y1[i], y1[order[1:]])
        xx2 = np.minimum(x2[i], x2[order[1:]])
        yy2 = np.minimum(y2[i], y2[order[1:]])

        w = np.maximum(0.0, xx2 - xx1 + 1)
        h = np.maximum(0.0, yy2 - yy1 + 1)
        inter = w * h
        ovr = inter / (areas[i] + areas[order[1:]] - inter)

        inds = np.where(ovr <= thresh)[0]
        order = order[inds + 1]

    return keep

三、模板匹配代码

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
Descripttion: 
version: 1.0
Author:
Date: 2020-09-21 17:29:05
LastEditors: 
LastEditTime: 2020-09-29 16:55:43
Software:: Visual Studio Code
FilePath: image_match.py
'''
from cv2 import cv2
import numpy as np
from nms import py_cpu_nms
import time

# 金字塔缩放参数,需要根据实际情况进行调整
scale_factor = 1 / 1.2

# 图像缩放
def processed_image(image, scale):
    height, width = image.shape
    new_height = int(height * scale)
    new_width = int(width * scale)
    new_dim = (new_width, new_height)
    img_resized = cv2.resize(image, new_dim, interpolation=cv2.INTER_LINEAR)
    return img_resized


# 图像金字塔
def pyramid_image(image, current_scale=1.0):
    min_h = 12
    min_w = 12
    dim_h = 0
    dim_w = 0
    ratios = []
    images = []
    if len(image.shape) < 3:
        dim_h, dim_w = image.shape
    else:
        dim_h, dim_w, dim_c = image.shape
    while (dim_h > min_h and dim_w > min_w):
        current_scale *= scale_factor
        resized_img = processed_image(image, current_scale)
        images.append(resized_img)
        ratios.append(current_scale)
        dim_h, dim_w = resized_img.shape
    return images, ratios



def image_match(gray_src, tpl, methods, threshold=0.62):
    box_rec = []
    h, w = tpl.shape[:2]

    # 模板不能大于图像
    if h > min(gray_src.shape[:2]) or w > min(gray_src.shape[:2]):
        return box_rec
    res = cv2.matchTemplate(gray_src, tpl, methods)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
    print(max_val)
    loc = np.where(res >= threshold)
    for pt in zip(*loc[::-1]):
        xmin = pt[0]
        ymin = pt[1]
        xmax = pt[0] + w
        ymax = pt[1] + h 
        score = res[pt[1]][pt[0]]
        # 搜索框在图像左边,排除右边的干扰区域
        if xmax < gray_src.shape[1] / 2:
            box_rec.append([xmin, ymin, xmax, ymax, score])
    box_rec = np.array(box_rec)
    if len(box_rec) != 0:
        keep = py_cpu_nms(box_rec, 0.3)
        box_rec = box_rec[keep]
    return box_rec



def pyramid_image_match(image,template,threshold=0.62):

    result_box = []
    if image is None or template_white is None or template_black is None:
        return np.array(result_box)
    h_ratio = 180. / 1080.
    height, width, channel = image.shape
    roi_y =0
    roi_h = int(h_ratio * height)
    roi_img = image[roi_y:roi_y + roi_h, 0:width]
    gray_roi_img = cv2.cvtColor(roi_img, cv2.COLOR_BGR2GRAY)
    gray_tem = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)

    current_scale = max(1.0, max(height * 1.0 / width, height / 1080.0))
    methods = cv2.TM_CCOEFF_NORMED
    if current_scale != 2339 / 1080.0:
        tmp_py_list, ratio_py_list = pyramid_image(gray_tem, current_scale)
        for tpl, tpl_ratio in zip(tmp_py_list, ratio_py_list):
            box_rec = image_match(gray_roi_img, tpl, methods, threshold)
            if len(box_rec) != 0:
                result_box.append(box_rec)
    else:
        box_rec = image_match(gray_roi_img, gray_tem, methods, threshold)
        if len(box_rec) != 0:
            result_box.append(box_rec)
    result_box = np.array(result_box)
    if result_box.size != 0:
        result_box = np.vstack(result_box)
        keep = py_cpu_nms(result_box, 0.3)
        result_box = result_box[keep]
        result_box.astype(int)

    return result_box


if __name__ == '__main__':
    image = cv2.imread("image.jpg")
    template = cv2.imread("template.jpg")
    start = time.time()
    box_res = pyramid_image_match(image, template)
    if box_res.size != 0:
        cv2.namedWindow('image', cv2.WINDOW_NORMAL)
        for box in box_res:
            box = box[:4].astype(int)
            cv2.rectangle(image, (box[0], box[1]), (box[2], box[3]),
                          (0, 0, 255), 2)
            cv2.imshow("image", image)
        cv2.waitKey(0)

参考网址:

  1. blog.csdn.net/weixin_4208…
  2. www.cnblogs.com/FHC1994/p/9…
  3. blog.csdn.net/liyuanbhu/a…
  4. www.jianshu.com/p/f291a9714…