【代码篇】计算两张图片的偏移量

目录

  • 需求
  • 方法一
  • 方法二
  • 纠偏后结果

需求

同一预置位的图像,不同时间段会出现偏差,因此需要计算偏差值,从而进行纠偏。
【代码篇】计算两张图片的偏移量_第1张图片
base.jpg
【代码篇】计算两张图片的偏移量_第2张图片
shift.jpg

方法一

思路:使用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])

方法二

思路:使用cv2.SIFT_create()找到两张图的相似点,再通过KDTree算法找到坐标差值最接近的大多数点,也就是最终两张图的偏移量。

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))

纠偏后结果

【代码篇】计算两张图片的偏移量_第3张图片

你可能感兴趣的:(OpenCV,opencv,python,计算机视觉)