import glob
import time
import numpy as np
import matplotlib.pyplot as plt
import cv2
import os
import threading
def stitch(index, images, outResult, outResult1, images_output):
result = images[0] # 将第一张图像作为初始结果
number = len(images)
result1 = images_output[index*number] # 将第一张图像作为初始结果
for i in range(1, len(images)): # 从第二张图像开始遍历
imageLeft = result
imageRight = images[i]
imageLeft1 = result1
imageRight1 = images_output[index*number + i]
if imageLeft is None or imageRight is None:
print("NOTICE: No images")
else:
ImageLeft_gray = cv2.cvtColor(imageLeft, cv2.COLOR_BGR2GRAY)
ImageRight_gray = cv2.cvtColor(imageRight, cv2.COLOR_BGR2GRAY)
# 获取图像长宽
height_Left, width_left = ImageLeft_gray.shape[:2]
height_Right, width_Right = ImageRight_gray.shape[:2]
beishu = height_Left / 5120
height = int(1000 * beishu)
# 模板区域
left_width_begin = int(width_left - int(2000 * beishu))
left_height_begin = height
template_left = imageLeft[int(left_height_begin):int(2 * height_Left / 3),
int(left_width_begin): int(width_left - int(100 * beishu))]
# 右边匹配区域
match_right = imageRight[0:height_Right, 0: int(2 * width_Right / 3)]
# 执行模板匹配,采用的匹配方式cv2.TM_CCOEFF_NORMED
matchResult = cv2.matchTemplate(match_right, template_left, cv2.TM_CCOEFF_NORMED)
# 归一化处理
cv2.normalize(matchResult, matchResult, 0, 1, cv2.NORM_MINMAX, -1)
# 寻找矩阵(一维数组当做向量,用Mat定义)中的最大值和最小值的匹配结果及其位置
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(matchResult)
# 设置最终图片大小
dstStitch = np.zeros((height_Left, width_Right + left_width_begin - max_loc[0], 3), imageLeft.dtype)
dstStitch1 = np.zeros((height_Left, width_Right + left_width_begin - max_loc[0], 3), imageLeft1.dtype)
height_dst, width_dst = dstStitch.shape[:2]
# copy left image
dstStitch[0:height_Left, 0:width_left] = imageLeft.copy()
dstStitch1[0:height_Left, 0:width_left] = imageLeft.copy()
# 匹配右图的高要能和目标区域一样
matchRight_H = height_Right - max_loc[1] + left_height_begin
if height_dst == matchRight_H:
matchRight = imageRight[int(max_loc[1] - left_height_begin): int(height_Right),
int(max_loc[0]):int(width_Right)]
matchRight = matchRight[:, int(1000 * beishu):]
matchRight1 = imageRight1[int(max_loc[1] - left_height_begin): int(height_Right),
int(max_loc[0]):int(width_Right)]
matchRight1 = matchRight1[:, int(1000 * beishu):]
elif height_dst < matchRight_H:
dst_y_start = (left_height_begin - max_loc[1])
# 定义平移矩阵
M = np.float32([[1, 0, 0], [0, 1, dst_y_start]]) # 向上平移 dst_y_start个像素
# 应用平移矩阵
rows, cols, _ = imageRight.shape
matchRight = cv2.warpAffine(imageRight, M, (cols, rows))
matchRight = matchRight[0: height_Right, max_loc[0]:width_Right]
matchRight = matchRight[:, int(1000 * beishu):]
matchRight1 = cv2.warpAffine(imageRight1, M, (cols, rows))
matchRight1 = matchRight1[0: height_Right, max_loc[0]:width_Right]
matchRight1 = matchRight1[:, int(1000 * beishu):]
else:
dst_y_start = (left_height_begin - max_loc[1])
# 定义平移矩阵
M = np.float32([[1, 0, 0], [0, 1, dst_y_start]]) # 向下平移 dst_y_start个像素
# 应用平移矩阵
rows, cols, _ = imageRight.shape
matchRight = cv2.warpAffine(imageRight, M, (cols, rows))
matchRight = matchRight[0: height_Right, max_loc[0]:width_Right]
matchRight = matchRight[:, int(1000 * beishu):]
matchRight1 = cv2.warpAffine(imageRight1, M, (cols, rows))
matchRight1 = matchRight1[0: height_Right, max_loc[0]:width_Right]
matchRight1 = matchRight1[:, int(1000 * beishu):]
drawRightRect = imageRight.copy()
drawRightRect1 = imageRight1.copy()
h, w = template_left.shape[:2]
cv2.rectangle(drawRightRect, (max_loc[0], max_loc[1]), (max_loc[0] + w, max_loc[1] + h), (0, 0, 255), 1)
cv2.rectangle(drawRightRect1, (max_loc[0], max_loc[1]), (max_loc[0] + w, max_loc[1] + h), (0, 0, 255), 1)
height_mr, width_mr = matchRight.shape[:2]
dstStitch[0:height_dst,
left_width_begin + int(1000 * beishu):width_mr + int(1000 * beishu) + left_width_begin] = matchRight.copy()
dstStitch1[0:height_dst,
left_width_begin + int(1000 * beishu):width_mr + int(1000 * beishu) + left_width_begin] = matchRight1.copy()
result = dstStitch
result1 = dstStitch1
# file_name = f'E:/camera/pailei/{i}.jpg' # 使用f-string创建不同的文件名
# plt.imsave(file_name, cv2.cvtColor(result, cv2.COLOR_BGR2RGB))
result = cv2.rotate(result, cv2.ROTATE_90_COUNTERCLOCKWISE)
result1 = cv2.rotate(result1, cv2.ROTATE_90_COUNTERCLOCKWISE)
outResult.update({str(index): result})
outResult1.update({str(index): result1})
def stitch_start(input, output , number):
if "\\" in input[0]:
input = sorted(input, key=lambda x: int(x.split("\\")[-1][:-4]))
else:
input = sorted(input, key=lambda x: int(x.split("/")[-1][:-4]))
if "\\" in output[0]:
output = sorted(output, key=lambda x: int(x.split("\\")[-1][:-4]))
else:
output = sorted(output, key=lambda x: int(x.split("/")[-1][:-4]))
images_output = []
for filename1 in output:
image = cv2.imread(filename1) # 使用OpenCV库读取图像文件
images_output.append(image) # 将图像添加到列表中
images = [] # 用来存储读取的图像
for filename in input:
image = cv2.imread(filename) # 使用OpenCV库读取图像文件
images.append(image) # 将图像添加到列表中
beishu = images[1].shape[0] / 5120
imgs = {}
row_imgs = []
size = len(images)//number
for i in range(size):
for j in range(number):
row_imgs.append(images[i*number+j])
imgs.update({str(i): row_imgs})
row_imgs = []
# images2 = [] # 用来存储读取的图像
row_stitch_img = {}
row_stitch_img1 = {}
thread_list = []
for i in range(size):
images = imgs[str(i)]
th = threading.Thread(target = stitch, args=(i, images, row_stitch_img, row_stitch_img1,images_output,))
thread_list.append(th)
th.start()
for th in thread_list:
th.join()
# result = stitch(images,)
# images2.append(result)
if len(row_stitch_img) != 0 :
result = row_stitch_img[str(0)] # 将第一张图像作为初始结果
result1 = row_stitch_img1[str(0)] # 将第一张图像作为初始结果
n = 0
if len(row_stitch_img) != 0:
for i in range(1, len(row_stitch_img)): # 从第二张图像开始遍历
imageLeft = result
imageRight = row_stitch_img[str(i)]
imageLeft1 = result1
imageRight1 = row_stitch_img1[str(i)]
# 获取图像长宽
height_Left, width_left = imageLeft.shape[:2]
height_Right, width_Right = imageRight.shape[:2]
# min_width = min(width_left,width_Right)
min_height = min(height_Left,height_Right)
# 裁剪图像
imageLeft = imageLeft[:min_height, :]
imageRight = imageRight[:min_height, :]
# # 将第二张图调整为和第一张图一样的高度
# imageRight = cv2.resize(imageRight, (imageRight.shape[1], height),interpolation=cv2.INTER_LINEAR)
# if i==2:
# break
if imageLeft is None or imageRight is None:
print("NOTICE: No images")
else:
ImageLeft_gray = cv2.cvtColor(imageLeft, cv2.COLOR_BGR2GRAY)
ImageRight_gray = cv2.cvtColor(imageRight, cv2.COLOR_BGR2GRAY)
# cv2.imshow("gray", ImageLeft_gray)
# cv2.waitKey()
# 获取图像长宽
height_Left, width_left = ImageLeft_gray.shape[:2]
height_Right, width_Right = ImageRight_gray.shape[:2]
height = int(1000 * beishu)
# 模板区域
left_width_begin = int(width_left - int(2000 * beishu))
left_height_begin = height
template_left = imageLeft[int(left_height_begin):int(height_Left-int(1000*beishu)),
int(left_width_begin): int(width_left - int(200 * beishu))]
# drawLeftRect = imageLeft.copy()
# cv2.rectangle(drawLeftRect, (left_width_begin, left_height_begin), (width_left, int(4 * height_Left / 5)),
# (0, 0, 255),
# 1)
# cv2.imshow("template_left", drawLeftRect)
# cv2.waitKey()
# plt.imsave('Left_rect.jpg', cv2.cvtColor(drawLeftRect, cv2.COLOR_BGR2RGB))
# 右边匹配区域
match_right = imageRight[0:height_Right, 0: int(1* width_Right / 2)]
# cv2.imshow("match_right", match_right)
# cv2.waitKey()
# 执行模板匹配,采用的匹配方式cv2.TM_CCOEFF_NORMED
matchResult = cv2.matchTemplate(match_right, template_left, cv2.TM_CCOEFF_NORMED)
# cv2.imwrite('2.jpg', matchResult)
# 归一化处理
cv2.normalize(matchResult, matchResult, 0, 1, cv2.NORM_MINMAX, -1)
# 寻找矩阵(一维数组当做向量,用Mat定义)中的最大值和最小值的匹配结果及其位置
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(matchResult)
# print(max_loc)
# cv2.rectangle(imageRight, (max_loc[0], max_loc[1]), (width_left-left_width_begin + max_loc[0], max_loc[1] + int(height_Left / 2)), (0, 0, 255),
# 1)
# plt.imsave('Right_rect.jpg', cv2.cvtColor(imageRight, cv2.COLOR_BGR2RGB))
# 设置最终图片大小
dstStitch = np.zeros((height_Left, width_Right + left_width_begin - max_loc[0], 3), imageLeft.dtype)
dstStitch1 = np.zeros((height_Left, width_Right + left_width_begin - max_loc[0], 3), imageLeft1.dtype)
height_dst, width_dst = dstStitch.shape[:2]
# copy left image
dstStitch[0:height_Left, 0:width_left] = imageLeft.copy()
dstStitch1[0:height_Left, 0:width_left] = imageLeft.copy()
# 匹配右图的高要能和目标区域一样
matchRight_H = height_Right - max_loc[1] + left_height_begin
if height_dst == matchRight_H:
matchRight = imageRight[int(max_loc[1] - left_height_begin): int(height_Right),
int(max_loc[0]):int(width_Right)]
matchRight = matchRight[:, int(1000 * beishu):]
matchRight1 = imageRight1[int(max_loc[1] - left_height_begin): int(height_Right),
int(max_loc[0]):int(width_Right)]
matchRight1 = matchRight1[:, int(1000 * beishu):]
elif height_dst < matchRight_H:
dst_y_start = (left_height_begin - max_loc[1])
# 定义平移矩阵
M = np.float32([[1, 0, 0], [0, 1, dst_y_start]]) # 向上平移 dst_y_start个像素
# 应用平移矩阵
rows, cols, _ = imageRight.shape
matchRight = cv2.warpAffine(imageRight, M, (cols, rows))
matchRight = matchRight[0: height_Right, max_loc[0]:width_Right]
matchRight = matchRight[:, int(1000 * beishu):]
matchRight1 = cv2.warpAffine(imageRight1, M, (cols, rows))
matchRight1 = matchRight1[0: height_Right, max_loc[0]:width_Right]
matchRight1 = matchRight1[:, int(1000 * beishu):]
else:
dst_y_start = (left_height_begin - max_loc[1])
# 定义平移矩阵
M = np.float32([[1, 0, 0], [0, 1, dst_y_start]]) # 向下平移 dst_y_start个像素
# 应用平移矩阵
rows, cols, _ = imageRight.shape
matchRight = cv2.warpAffine(imageRight, M, (cols, rows))
matchRight = matchRight[0: height_Right, max_loc[0]:width_Right]
matchRight = matchRight[:, int(1000 * beishu):]
matchRight1 = cv2.warpAffine(imageRight1, M, (cols, rows))
matchRight1 = matchRight1[0: height_Right, max_loc[0]:width_Right]
matchRight1 = matchRight1[:, int(1000 * beishu):]
drawRightRect = imageRight.copy()
drawRightRect1 = imageRight1.copy()
h, w = template_left.shape[:2]
cv2.rectangle(drawRightRect, (max_loc[0], max_loc[1]), (max_loc[0] + w, max_loc[1] + h), (0, 0, 255), 1)
cv2.rectangle(drawRightRect1, (max_loc[0], max_loc[1]), (max_loc[0] + w, max_loc[1] + h), (0, 0, 255),
1)
height_mr, width_mr = matchRight.shape[:2]
dstStitch[0:height_dst,
left_width_begin + int(1000 * beishu):width_mr + int(
1000 * beishu) + left_width_begin] = matchRight.copy()
dstStitch1[0:height_dst,
left_width_begin + int(1000 * beishu):width_mr + int(
1000 * beishu) + left_width_begin] = matchRight1.copy()
result = dstStitch
result1 = dstStitch1
# file_name = f'E:/camera/pailei/{i}.jpg' # 使用f-string创建不同的文件名
# plt.imsave(file_name, cv2.cvtColor(result, cv2.COLOR_BGR2RGB))
if len(row_stitch_img) != 0:
# file_name = f"{i}.jpg"
dstStitch = cv2.rotate(dstStitch, cv2.ROTATE_90_CLOCKWISE)
dstStitch1 = cv2.rotate(dstStitch1, cv2.ROTATE_90_CLOCKWISE)
# # 进行水平镜像翻转
# dstStitch = cv2.flip(dstStitch, 1)
# dstStitch = cv2.flip(dstStitch, 0)
if len(row_stitch_img) == 1:
dstStitch = row_stitch_img[str(0)]
dstStitch1 = row_stitch_img1[str(0)]
# # 进行水平镜像翻转
# dstStitch = cv2.flip(dstStitch, 1)
# dstStitch = cv2.flip(dstStitch, 0)
if len(row_stitch_img) == 1:
dstStitch = row_stitch_img[str(0)]
dstStitch = cv2.rotate(dstStitch, cv2.ROTATE_90_CLOCKWISE)
dstStitch1 = row_stitch_img1[str(0)]
dstStitch1 = cv2.rotate(dstStitch1, cv2.ROTATE_90_CLOCKWISE)
# # 进行水平镜像翻转
# dstStitch = cv2.flip(dstStitch, 1)
# dstStitch = cv2.flip(dstStitch, 0)
save_path = './/results//stitch//stitch.jpg'
cv2.imwrite(save_path, dstStitch)
cv2.imwrite("result.jpg",dstStitch)
cv2.imwrite("result1.jpg",dstStitch1)
return 1, os.path.abspath(save_path)
if __name__ == "__main__":
input = glob.glob(r"A1A2A3_V1/UP/*.jpg")
images_output = glob.glob(r"A1A2A3_V1/UP/*.jpg")
stitch_start(input, images_output, 4)
10-28
6748