利用opencv做图像匹配

原创
2022/10/21 14:13
阅读数 174

最近有个小活儿,设备拍了一系列图片,但在这些图片里目标物会动,希望把目标物尽可能稳住,这样最终用这些图片合成的视频可以更加关注目标本身的变化,而不是目标的移动。

 

写了个很简单的脚本实现了,效果还可以,在此记录一下。

# -*- coding: utf-8 -*-
"""
包括滤波、锐化、匹配、生成图片,最终使得移动的目标物看起来仿佛没有移动
"""

import numpy as np
import cv2
import os, sys

METHOD = cv2.TM_SQDIFF_NORMED # cv2.TM_CCORR_NORMED, cv2.TM_CCOEFF_NORMED
SHIFT = 100  // 目标物最大移动距离,估计值
ROWS = 0
COLS = 0
FPS = 24

# 获得所有图片文件名
def readfig(path):
    figs = []
    for root, dirs, files in os.walk(path):
        for file in files:
            figs.append(file)
    return figs

# 傅里叶变换处理
def dft(fig):
    global ROWS, COLS
    img_float32 = np.float32(fig)
    dft = cv2.dft(img_float32, flags = cv2.DFT_COMPLEX_OUTPUT)
    
    mask = np.ones((ROWS, COLS, 2), np.uint8)
    row_cut = ROWS//5
    col_cut = COLS//5
    mask[ROWS-row_cut:, COLS-col_cut:] = 0

    img_back = cv2.idft(dft*mask)
    img_back = cv2.magnitude(img_back[:,:,0], img_back[:,:,1])

    img_max = np.max(img_back)
    result = np.uint8(img_back/img_max*255)  # 将图中的值转换为0-255

    return result

# 滤波
def filter(img):
    block_size = 11
    # 平均滤波
    #kernel = np.ones((5,5), np.float32)/25
    #dst = cv2.filter2D(img, -1, kernel, anchor=None)
    # 另一种平均滤波
    #dst = cv2.blur(img, (block_size, block_size))
    # 高斯滤波
    #sigmaX = sigmaY = 10
    #dst = cv2.GaussianBlur(img, (block_size, block_size), sigmaX, sigmaY)
    # 中值滤波
    dst = cv2.medianBlur(img, block_size)
    # 双边滤波
    #sigmaColor = 5
    #sigmaSpace = 5
    #dst = cv2.bilateralFilter(img, block_size, sigmaColor, sigmaSpace)
    return dst

# 二值化
def threshold(fig):
    #ret, dst = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV)
    #dst = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, block_size, const)
    ret, dst = cv2.threshold(fig, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
    return dst

# 模板匹配
def match(target, template):
    global METHOD
    result = cv2.matchTemplate(target, template, METHOD)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
    return min_loc

# 平移原图并保存
def savefig(video, path, fig, step=(0,0)):
    global ROWS, COLS
    Mat = np.float32([[1, 0, step[0]], [0, 1, step[1]]])
    dst_img = cv2.warpAffine(fig, Mat, (COLS, ROWS))
    cv2.imwrite(path, dst_img)
    video.write(dst_img)

if __name__ == "__main__":
    figs = readfig("src_img")
    fourcc = cv2.VideoWriter_fourcc(*'X264')

    target_origin = cv2.imread("src_img/" + figs[0], 0)
    ROWS, COLS = target_origin.shape
    target_filtered = filter(target_origin)
    target_sharpened = threshold(target_filtered)
    video = cv2.VideoWriter("test.mp4", fourcc, FPS, target_origin.shape)
    savefig(video, "dst_img/"+figs[0], target_origin)
    for i in range(1, len(figs)):
        print(figs[i] + " process begin:")
        template_origin = cv2.imread("src_img/" + figs[i], 0)
        template_filtered = filter(template_origin)
        template_sharpened = threshold(template_filtered)
        template = template_sharpened[SHIFT:ROWS-SHIFT, SHIFT:COLS-SHIFT]
        location = match(target_sharpened, template)
        row_shift = location[0] - SHIFT
        col_shift = location[1] - SHIFT
        savefig(video, "dst_img/" + figs[i], template_origin, (row_shift, col_shift))
        print(figs[i] + " process completed...\n")

    video.release()

其实还可以利用傅里叶变换做一些处理,但因为目前效果就已经很好了,因此上面的傅里叶变换都没用到。

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部