本代码可实现对一个文件夹下的所有图片都进行局部的放大、展示、保存。并可以通过设置resize_factor变量实现图像在显示时的缩放,而不影响实际图像的分辨率操作(仅在显示时缩放)以免图像太大了,在cv交互界面显示的不全。
请注意:本代码操作流程如下:
- 设置好代放大图像的路径,以及用于保存放大结果的路径,运行该python代码
- 鼠标点击左键,按住左键,由左上到右下选取一个矩形框
- 按s键,进行保存
- 可多次进行2、3步骤,实现多个地方的局部放大保存
- 保存处理完后,按q,退出程序
'''
本版本代码可以对超大图像(例如分辨率标靶图)进行选取部分放大,并形成小图保存
'''
import cv2
import numpy as np
import os
# 全局变量
drawing = False # 是否正在绘制矩形框
start_x, start_y = -1, -1 # 矩形框左上角坐标
end_x, end_y = -1, -1 # 矩形框右下角坐标
image_copy = None # 原图的副本
rect_coordinates = None # 保存矩形框的坐标
resize_factor = 0.1 # 显示时的缩放比例
scaled_image = None # 用于显示的缩小版本
def resize_image(image, scale):
"""缩放图像"""
height, width = image.shape[:2]
new_size = (int(width * scale), int(height * scale))
return cv2.resize(image, new_size)
def save_magnify(image, a, b, save_path=None): # a:矩形框左上角坐标; b:矩形框右下角坐标
lw = 2 # 边框宽度
# 截出放大的部分
img_magnify = image[a[1] - lw:b[1] + lw, a[0] - lw:b[0] + lw, :]
# 计算缩放比例
new_W = image.shape[1] - 2 * lw
ratio = float(new_W) / img_magnify.shape[1]
# 根据缩放比例计算缩放后的尺寸
new_height = int(img_magnify.shape[0] * ratio)
new_size = (new_W, new_height)
# 进行缩放
resized_image = cv2.resize(img_magnify, new_size)
# 添加边框
border_size = lw
border_color = (0, 0, 255) # 红色
resized_image = cv2.copyMakeBorder(resized_image, border_size, border_size, border_size, border_size,
cv2.BORDER_CONSTANT, value=border_color)
# 画矩形框
cv2.rectangle(image, a, b, (0, 0, 255), lw)
# 拼接原图和放大部分
patch = np.vstack((image, resized_image))
# 保存结果
if save_path:
cv2.imwrite(save_path, patch)
print(f"放大区域保存至:{save_path}")
def draw_rectangle(event, x, y, flags, param):
global drawing, start_x, start_y, end_x, end_y, image_copy, rect_coordinates
if event == cv2.EVENT_LBUTTONDOWN: # 左键按下
drawing = True
start_x, start_y = int(x / resize_factor), int(y / resize_factor) # 转换为原图坐标
elif event == cv2.EVENT_MOUSEMOVE: # 鼠标移动
if drawing:
temp_image = scaled_image.copy()
cv2.rectangle(temp_image, (int(start_x * resize_factor), int(start_y * resize_factor)), (x, y), (0, 0, 255), 2)
cv2.imshow("Image", temp_image)
elif event == cv2.EVENT_LBUTTONUP: # 左键释放
drawing = False
end_x, end_y = int(x / resize_factor), int(y / resize_factor) # 转换为原图坐标
rect_coordinates = ((start_x, start_y), (end_x, end_y))
# 显示矩形框的左上角和右下角坐标
print(f"矩形框左上角坐标:({start_x}, {start_y})")
print(f"矩形框右下角坐标:({end_x}, {end_y})")
# 更新显示
cv2.rectangle(image_copy, (start_x, start_y), (end_x, end_y), (0, 0, 255), 2)
display_image = resize_image(image_copy, resize_factor) # 缩小显示
cv2.imshow("Image", display_image)
def process_folder(input_folder, output_folder, rect_coordinates):
if not os.path.exists(output_folder):
os.makedirs(output_folder)
file_list = [f for f in os.listdir(input_folder) if f.lower().endswith(('png', 'jpg', 'jpeg'))]
if not file_list:
print("文件夹中没有图像文件!")
return
a, b = rect_coordinates
for idx, file_name in enumerate(file_list):
file_path = os.path.join(input_folder, file_name)
save_path = os.path.join(output_folder, f"magnified_{file_name}")
image = cv2.imread(file_path)
if image is None:
print(f"无法加载图像:{file_name}")
continue
save_magnify(image, a, b, save_path)
if __name__ == '__main__':
# 输入图像文件夹路径
input_folder = r'E:\to_be_big_images' # 输入文件夹路径
output_folder = r'E:\bigger_images' # 输出文件夹路径
# 读取文件夹中的第一张图像
file_list = [f for f in os.listdir(input_folder) if f.lower().endswith(('png', 'jpg', 'jpeg'))]
if not file_list:
print("文件夹中没有图像文件!")
exit()
first_image_path = os.path.join(input_folder, file_list[0])
image = cv2.imread(first_image_path)
if image is None:
print("无法加载第一张图像!")
exit()
# 创建图像副本
image_copy = image.copy()
scaled_image = resize_image(image_copy, resize_factor) # 缩小显示版本
# 创建窗口并显示图像
cv2.namedWindow("Image")
cv2.imshow("Image", scaled_image)
# 设置鼠标回调函数
cv2.setMouseCallback("Image", draw_rectangle)
# 循环等待按键事件
while True:
key = cv2.waitKey(1) & 0xFF
# 按下 's' 键保存所有放大区域并对整个文件夹进行处理
if key == ord('s'):
if rect_coordinates is not None:
print("开始处理文件夹中的所有图像...")
process_folder(input_folder, output_folder, rect_coordinates)
print("所有图像处理完成!")
else:
print("请先选择矩形区域!")
# 按下 'q' 键 或者 退出窗口时退出程序
if key == ord('q') or cv2.getWindowProperty("Image", cv2.WND_PROP_VISIBLE) < 1:
break
cv2.destroyAllWindows()
最后的保存效果如下: