Table of contents
need
The image at the same preset position will deviate in different time periods, so it is necessary to calculate the deviation value to correct the deviation.
base.jpg
shift.jpg
method one
Idea: Use 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])
Method Two
Idea: Use cv2.SIFT_create() to find the similarities between the two images, and then use the KDTree algorithm to find most of the points with the closest coordinate difference, which is the offset of the final two images.
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))