同一预置位的图像,不同时间段会出现偏差,因此需要计算偏差值,从而进行纠偏。
base.jpg
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))