[Código] Calcular el desplazamiento de dos imágenes

necesidad

La imagen de la misma posición preestablecida se desviará en diferentes períodos de tiempo, por lo que es necesario calcular el valor de desviación para corregir la desviación.
Foto 1
base.jpg
inserte la descripción de la imagen aquí
turno.jpg

método uno

Idea: Usar cv2.phaseCorrelate(src1,src2)

import os.path

import cv2
import numpy as np
import time
base_path = "/home/data/wangchunyue/code/offset/jpg3/22/"
src1_path = os.path.join(base_path, "base.png")
src2_path = os.path.join(base_path, "shift.jpg")
src1 = cv2.imread(src1_path)
src2 = cv2.imread(src2_path)
src1 = src1[100:src1.shape[0]-100,0:src1.shape[1]]
src2 = src2[100:src2.shape[0]-100,0:src2.shape[1]]
add_img = cv2.addWeighted(src1, 0.5, src2, 0.5, 1)  # 图像融合,方便显示

src1 = np.float32(src1)
src2 = np.float32(src2)
src1 = cv2.cvtColor(src1, cv2.COLOR_BGR2GRAY)
src2 = cv2.cvtColor(src2, cv2.COLOR_BGR2GRAY)

# 函数说明:利用傅里叶变化,在频域进行相位匹配从而计算两张图片的平移量
start_time = time.time()
dst = cv2.phaseCorrelate(src1,src2)
end_time =time.time()
print("offsetv1 = {:.4f}s".format(end_time-start_time))
cv2.putText(add_img,str(dst[0]),(100,100),cv2.FONT_HERSHEY_COMPLEX,1, (0,255,0), 3)
cv2.imwrite(base_path + "\\" + "{}.jpg".format(src1_path.split("\\")[-1][:-4] +"+"+ src2_path.split("\\")[-1][:-4]), add_img)
print(dst[0])

Método dos

Idea: Use cv2.SIFT_create() para encontrar las similitudes entre las dos imágenes y luego use el algoritmo KDTree para encontrar la mayoría de los puntos con la diferencia de coordenadas más cercana, que es el desplazamiento de las dos imágenes finales.

import cv2
import numpy as np
import glob
import os
from tqdm import tqdm
import shutil
from sklearn.neighbors import KDTree
import time


def BFMatchV2(img1, img2):
    # 函数说明:sift算法用于识别两张图的相似点
    # 输入参数:一张底图,一张检测图,并且经过裁剪操作
    # 输出参数:所有的坐标差值
    # sift = cv2.xfeatures2d.SIFT_create()
    sift = cv2.SIFT_create()
    keypoints_1, descriptors_1 = sift.detectAndCompute(img1, None)
    keypoints_2, descriptors_2 = sift.detectAndCompute(img2, None)
    bf = cv2.BFMatcher(cv2.NORM_L1, crossCheck=True)
    matches = bf.match(descriptors_1, descriptors_2)
    matches = sorted(matches, key=lambda x: x.distance)
    print(len(matches))
    img3 = cv2.drawMatches(img1, keypoints_1, img2, keypoints_2, matches[:10], img2, flags=2)
    #cv2.imwrite(result_path + "/" + "line.jpg", img3)
    Result = []
    for match in matches[:2000]:
        p1 = keypoints_1[match.queryIdx].pt
        p2 = keypoints_2[match.trainIdx].pt
        result = list(p2)[0] - list(p1)[0], list(p2)[1] - list(p1)[1]
        Result.append(result)
    return Result


def KDTreeQuery(Result):  
    # 函数说明:KDTree是一种聚类算法,用于计算坐标差值最接近的大多数点
    # 输入参数:所有的坐标差值
    # 输出参数:坐标差值最接近的大多数点中的第一个元素
    tree = KDTree(Result)
    all_nn_indices = tree.query_radius(Result, r=1.5)
    all_nns = [[Result[idx] for idx in nn_indices] for nn_indices in all_nn_indices]
    dic = dict()
    for nns in all_nns:
        dic[len(nns)] = nns
    result = dic[max(dic.keys())][0]
    return result


def SegImage(src1, src2):
    # 函数说明:用于将图片切分为上下两部分,并利用BFMatch函数,计算上下部分的所有的坐标差值
    # 输入参数:一张底图,一张检测图,没有经过裁剪操作
    # 输出参数:所有的坐标差值
    idx = [[130, 540, 0, 0], [540, 130, 0, 0]]
    add_result = []
    for i in range(2):
        print(idx[i][0], src1.shape[0] - idx[i][1], idx[i][2], src1.shape[1] - idx[i][3])
        dst1 = src1[idx[i][0]:src1.shape[0] - idx[i][1], idx[i][2]:src1.shape[1] - idx[i][3]]
        dst2 = src2[idx[i][0]:src2.shape[0] - idx[i][1], idx[i][2]:src2.shape[1] - idx[i][3]]
        result = BFMatchV2(dst1, dst2)
        print(dst1.shape,dst2.shape)
        add_result.extend(result)
    return add_result


if __name__ == "__main__":
    # 用于批量读取base_dir文件夹中的所有子文件数据,底图需要重命名为base,后缀名不做要求
    base_dir = "/data1/test/pianyi_v2/hntest/"
    paths = glob.glob(base_dir + "/*/" + 'base*')
    vesion = time.strftime('%Y-%m-%d-%H-%M-%S', time.localtime(time.time()))
    file_name = base_dir.split("/")[-2]
    results_path = os.path.join(base_dir, '..', "_{}_result_{}".format(file_name, vesion))
    # 将原图和检测图拷贝到新的文件夹,用于对比数据
    for path in tqdm(paths):
        base_path = os.path.dirname(path)
        result_path = results_path + "/" + base_path.split("/")[-1]
        if not os.path.exists(result_path):
            shutil.copytree(base_path, result_path)
    # 开始计算底图和检测图的偏移量
    for path in tqdm(paths):
        root_path = os.path.dirname(path)
        result_path = results_path + "/" + root_path.split("/")[-1]
        src1_path = path
        files = os.listdir(root_path)
        for file in files:
            src1 = cv2.imdecode(np.fromfile(src1_path, dtype=np.uint8), 1)
            src1 = src1.copy()
            if "base" not in file:
                src2_path = root_path + "/" + file
                src2 = cv2.imdecode(np.fromfile(src2_path, dtype=np.uint8), 1)
                dst1 = src2.copy()
                rows, cols = dst1.shape[0], dst1.shape[1]
                add_img = cv2.addWeighted(src1, 0.5, src2, 0.5, 1)
                add_result = SegImage(src1, src2)
                print(len(add_result))
                result =KDTreeQuery(add_result)
                pic_name = file[:-4]
                MAT = np.float32([[1, 0, -result[0]], [0, 1, -result[1]]])
                dst2 = cv2.warpAffine(dst1, MAT, (cols, rows), borderValue=(255, 255, 255))
                cv2.putText(dst2, str(result), (100, 100), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 3)
                cv2.imencode('.jpg', dst2)[1].tofile(result_path + "/" + "correct_{}.jpg".format(pic_name))

Resultado después de la corrección

inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/weixin_42326479/article/details/127747602
Recomendado
Clasificación