Tabla de contenido
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.
base.jpg
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))