html_img_map图分块加链接

本文全面覆盖信息技术领域的各个方面,从基础的前端开发、后端开发到移动应用开发,再到游戏开发、大数据开发、AI音视频处理等前沿技术。深入探讨了开发工具、嵌入式开发、音视频基础、图像处理、测试、基础运维、DevOps等关键领域,为读者提供了一站式的IT技术指南。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<div style="text-align:center">
      <img src="/shop/school/tzbar/imgs/tz-01.jpg" border="0" usemap="#tzbar_map1"/>
	  <map name="tzbar_map1" id="tzbar_map1">
	     <area shape="rect" coords="165,190,311,210" href="/shop/index.shtml" target="_blank"/>
	     <area shape="rect" coords="354,190,518,210" href="/shop/school/index.shtml" target="_blank"/>
	     <area shape="rect" coords="591,190,704,210" href="/shop/school/swk.shtml" target="_blank"/>
	     <area shape="rect" coords="759,190,880,210" href="/shop/school/tc.shtml" target="_blank"/>
	  </map>
	</div>

 

import cv2 import numpy as np import matplotlib.pyplot as plt import matplotlib as mpl # 设置Matplotlib中文字体 mpl.rcParams['font.sans-serif'] = ['SimHei'] mpl.rcParams['axes.unicode_minus'] = False # 相机内参和畸变系数 K = np.array([ [1881.4773 , 0 ,1016.363887], [0 , 1931.988488 , 547.1170723], [0 , 0 , 1]], dtype=np.float32) dist = np.array([-0.927214665,0.875249537,0.001301429,-0.006101325, 0], dtype=np.float32) # 控制点坐标 world_points_3d = np.array([ [4262845.751, 644463.054, 64.289], [4262844.149, 644468.755, 63.701], [4262846.106, 644470.001, 63.621], [4262847.099, 644471.268, 63.765], [4262853.252, 644455.049, 64.177], [4262846.305, 644431.715, 66.42], [4262851.769, 644434.948, 64.503], [4262852.526, 644431.694, 64.784], [4262858.526, 644426.641, 64.81], [4262865.608, 644419.362, 66.008], [4262858.634, 644475.401, 63.64], [4262868.267, 644480.64, 63.645], [4262871.129, 644477.184, 63.719] ], dtype=np.float32) image_points = np.array([ [205, 357], [31, 462], [74, 485], [88, 501], [593, 288], [525, 145], [644, 196], [674, 178], [815, 164], [968, 130], [748, 599], [1697, 763], [1739, 616] ], dtype=np.float32) # 读取像 raw_img = cv2.imread(r"D:\shuiwei\1.jpg") if raw_img is None: raise FileNotFoundError("无法像,请检查路径: D:\\shuiwei\\1.jpg") # 畸变校正 undistorted_img = cv2.undistort(raw_img, K, dist) # 修正后的旋转矩阵和平移向量 R = np.array([ [-0.99562414, -0.08557365, -0.03754638], [-0.01233105, -0.27796685, 0.96051152], [-0.09263113, 0.95677144, 0.27569529] ], dtype=np.float32) tvec = np.array([[4299360.374, 231647.0009, -221780.8828]], dtype=np.float32) tvec = tvec.reshape(3, 1) # 确保为3x1向量 # 计算水面平均高程 Z0 = np.mean(world_points_3d[:, 2]) print(f"水面平均高程: {Z0:.3f} 米") # 计算反投影函数 def inverse_project(points_2d, Z0): R_inv = np.linalg.inv(R) K_inv = np.linalg.inv(K) points_3d = [] for pt in points_2d: # 归一化坐标 uv = np.array([pt[0], pt[1], 1.0], dtype=np.float32) xyz_cam = K_inv @ uv # 计算射线方向 ray_dir = R_inv @ xyz_cam # 计算与高程平面相交的参数t # 方程: t * ray_dir[2] + (R_inv @ (-tvec))[2] = Z0 t = (Z0 - (R_inv @ (-tvec))[2, 0]) / ray_dir[2] # 计算世界坐标 P_c = t * xyz_cam P_w = R_inv @ (P_c - tvec) points_3d.append(P_w.flatten()) return np.array(points_3d) # 使用像边界反投影 img_height, img_width = undistorted_img.shape[:2] img_corners = np.array([ [0, 0], # 左上 [0, img_height], # 左下 [img_width, img_height], # 右下 [img_width, 0] # 右上 ], dtype=np.float32) # 反投影得到世界坐标 world_corners = inverse_project(img_corners, Z0) # 提取XY范围 X_min, X_max = np.min(world_corners[:, 0]), np.max(world_corners[:, 0]) Y_min, Y_max = np.min(world_corners[:, 1]), np.max(world_corners[:, 1]) # 扩展5%边界缓冲 x_range = X_max - X_min y_range = Y_max - Y_min X_min -= 0.05 * x_range X_max += 0.05 * x_range Y_min -= 0.05 * y_range Y_max += 0.05 * y_range print(f"正射影像范围: X: {X_min:.2f}-{X_max:.2f}, Y: {Y_min:.2f}-{Y_max:.2f}") # 设置分辨率 pixels_per_meter = 5 # 降低分辨率以速处理 width = int((X_max - X_min) * pixels_per_meter) height = int((Y_max - Y_min) * pixels_per_meter) print(f"正射影像尺寸: {width}x{height} 像素 (分辨率: {pixels_per_meter} 像素/米)") # 创建正射影像网格 ortho_x = np.linspace(X_min, X_max, width) ortho_y = np.linspace(Y_max, Y_min, height) # Y轴反转 ortho_xx, ortho_yy = np.meshgrid(ortho_x, ortho_y) ortho_zz = np.ones_like(ortho_xx) * Z0 # 将3D点展平 points_3d = np.dstack([ortho_xx, ortho_yy, ortho_zz]).reshape(-1, 3) # 世界坐标→像坐标 projected_points, _ = cv2.projectPoints( points_3d, R, tvec, K, None ) # 重塑为网格坐标 map_x = projected_points[:, 0, 0].reshape(ortho_xx.shape) map_y = projected_points[:, 0, 1].reshape(ortho_yy.shape) # 检查坐标范围有效性 valid_mask = (map_x >= 0) & (map_x < img_width) & \ (map_y >= 0) & (map_y < img_height) valid_percentage = np.mean(valid_mask) * 100 print(f"有效投影点比例: {valid_percentage:.2f}%") # 重映射生成正射影像 ortho_img = cv2.remap( undistorted_img, map_x.astype(np.float32), map_y.astype(np.float32), cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT, borderValue=(0, 0, 0) ) # 创建带透明通道的像 (RGBA) b, g, r = cv2.split(ortho_img) alpha = np.uint8(valid_mask * 255) ortho_img_rgba = cv2.merge([b, g, r, alpha]) # 保存结果 cv2.imwrite("river_ortho_corrected.png", ortho_img_rgba) # 可视化比较 plt.figure(figsize=(15, 10)) # 原始像 plt.subplot(131) plt.imshow(cv2.cvtColor(raw_img, cv2.COLOR_BGR2RGB)) plt.title("原始像") plt.axis('off') # 畸变校正后的像 plt.subplot(132) plt.imshow(cv2.cvtColor(undistorted_img, cv2.COLOR_BGR2RGB)) plt.title("畸变校正后像") plt.axis('off') # 正射影像(带透明通道) plt.subplot(133) # 将RGBA转换为RGB显示,透明部分显示为白色背景 ortho_rgb = cv2.cvtColor(ortho_img_rgba, cv2.COLOR_BGRA2RGBA) plt.imshow(ortho_rgb) plt.title(f"正射影像 ({width}x{height})\n有效区域: {valid_percentage:.1f}%") plt.axis('off') plt.tight_layout() plt.savefig("ortho_comparison.png", dpi=300, bbox_inches='tight') plt.show() # 保存调试像(投影点可视化) debug_img = undistorted_img.copy() for i, pt in enumerate(projected_points.reshape(-1, 2)): x, y = pt if 0 <= x < img_width and 0 <= y < img_height: color = (0, 255, 0) if i % 100 == 0 else (0, 0, 255) # 每隔100个点用绿色,其他用红色 cv2.circle(debug_img, (int(x), int(y)), 2, color, -1) cv2.imwrite("projection_debug.jpg", debug_img) # 计算重投影误差 reprojected, _ = cv2.projectPoints(world_points_3d, R, tvec, K, None) errors = np.linalg.norm(reprojected - image_points, axis=2) print(f"控制点重投影误差统计:") print(f" 最小: {np.min(errors):.2f} 像素") print(f" 最大: {np.max(errors):.2f} 像素") print(f" 平均: {np.mean(errors):.2f} 像素") print(f" 中位数: {np.median(errors):.2f} 像素")D:\Anaconda\python.exe D:\水位检测\正射校正\基于控制点的单应性变换.py 水面平均高程: 64.391 米 正射影像范围: X: 4262651.85-4262875.15, Y: 4262780.67-4262985.83 正射影像尺寸: 1116x1025 像素 (分辨率: 5 像素/米) 有效投影点比例: 0.00% 控制点重投影误差统计: 最小: 32.22 像素 最大: 2048.67 像素 平均: 737.62 像素 中位数: 632.97 像素
06-26
import os import argparse import sys import shutil from PIL import Image import time MAX_DIMENSION = 65000 # 最大允许尺寸(留500像素余量) SAFE_MODE = False # 设置为True可禁用删除操作(用于测试) def merge_images_with_chunks(input_dir, output_path=None, direction='vertical', spacing=0, background=(255, 255, 255)): """ 将多张片合并为多个长并清理原始片 """ # 自动生成输出文件名(如果未提供) if not output_path: timestamp = time.strftime("%Y%m%d_%H%M%S") output_path = os.path.join(input_dir, f"merged_{timestamp}.jpg") # 获取目录中的所有片文件(按文件名排序) valid_extensions = ('.jpg', '.jpeg', '.png', '.bmp', '.gif', '.webp') image_files = sorted([f for f in os.listdir(input_dir) if f.lower().endswith(valid_extensions)]) if not image_files: print(f"错误: 目录中没有片文件: {input_dir}") return False print(f"找到 {len(image_files)} 张片,开始合并...") # 准备变量 base_name, ext = os.path.splitext(output_path) current_chunk = 1 all_chunks = [] current_images = [] current_size = 0 # 当前块的总尺寸(高度或宽度) processed_files = [] # 记录已处理的原始片 for i, file in enumerate(image_files): try: img_path = os.path.join(input_dir, file) img = Image.open(img_path) img = img.convert('RGB') # 确保RGB模式 # 获取片尺寸 width, height = img.size img_size = height if direction == 'vertical' else width # 计算添片后的新尺寸 new_size = current_size + img_size if current_images: # 如果不是第一张,上间距 new_size += spacing # 检查是否需要创建新块 if new_size > MAX_DIMENSION and current_images: # 保存当前块 chunk_path = f"{base_name}_part{current_chunk}{ext}" if create_chunk(current_images, chunk_path, direction, spacing, background): all_chunks.append(chunk_path) print(f"已创建分块 {current_chunk}: {chunk_path}") # 重置变量,开始新块 current_chunk += 1 current_images = [] current_size = 0 new_size = img_size # 新块从当前片开始 # 添到当前块 current_images.append(img) processed_files.append(img_path) # 记录已处理的片 current_size = new_size print(f"添片 {i+1}/{len(image_files)}: {file} ({width}x{height})") except Exception as e: print(f"警告: 无法处理片 {file}: {str(e)}") # 处理最后一个块 if current_images: chunk_path = f"{base_name}_part{current_chunk}{ext}" if len(all_chunks) > 0 else output_path if create_chunk(current_images, chunk_path, direction, spacing, background): all_chunks.append(chunk_path) print(f"已创建分块 {current_chunk}: {chunk_path}") # 汇总结果 if all_chunks: print("\n合并完成! 共创建以下分块:") for path in all_chunks: print(f" - {path}") # 清理原始片 if not SAFE_MODE and processed_files: print("\n开始清理原始片...") for file_path in processed_files: try: os.remove(file_path) print(f"已删除: {os.path.basename(file_path)}") except Exception as e: print(f"删除失败: {os.path.basename(file_path)} - {str(e)}") print(f"\n已清理 {len(processed_files)} 张原始片") return True print("错误: 未能创建任何分块") return False def create_chunk(images, output_path, direction, spacing, background): """创建单个分块的长""" try: # 计算分块尺寸 if direction == 'vertical': total_width = max(img.width for img in images) total_height = sum(img.height for img in images) + spacing * (len(images) - 1) else: total_width = sum(img.width for img in images) + spacing * (len(images) - 1) total_height = max(img.height for img in images) # 创建像 chunk_img = Image.new('RGB', (total_width, total_height), background) # 粘贴片 offset = 0 for img in images: if direction == 'vertical': x_pos = (total_width - img.width) // 2 # 水平居中 chunk_img.paste(img, (x_pos, offset)) offset += img.height + spacing else: y_pos = (total_height - img.height) // 2 # 垂直居中 chunk_img.paste(img, (offset, y_pos)) offset += img.width + spacing # 保存分块 chunk_img.save(output_path) print(f" - 分块尺寸: {chunk_img.width}x{chunk_img.height}") return True except Exception as e: print(f"创建分块失败: {str(e)}") return False def main(): parser = argparse.ArgumentParser(description='片合并与清理工具') parser.add_argument('input_dir', help='包含片的目录路径') parser.add_argument('-o', '--output', help='输出文件路径 (可选,默认在输入目录生成)') parser.add_argument('-d', '--direction', choices=['vertical', 'horizontal'], default='vertical', help='合并方向: vertical(垂直) 或 horizontal(水平)') parser.add_argument('-s', '--spacing', type=int, default=0, help='片间距(像素)') parser.add_argument('-b', '--background', default='white', help='背景颜色 (颜色名称如 white/black, 或 RGB值如 255,255,255)') parser.add_argument('--safe', action='store_true', help='安全模式(不删除原始片)') args = parser.parse_args() # 处理安全模式 global SAFE_MODE SAFE_MODE = args.safe # 处理背景颜色 background = (255, 255, 255) # 默认白色 if args.background: try: # 尝试解析RGB值 (如 "255,255,255") if ',' in args.background: r, g, b = map(int, args.background.split(',')) background = (r, g, b) else: # 尝试颜色名称 from PIL import ImageColor background = ImageColor.getrgb(args.background) except: print(f"警告: 无法识别的颜色 '{args.background}', 使用默认白色") # 检查输入目录是否存在 if not os.path.isdir(args.input_dir): print(f"错误: 目录不存在: {args.input_dir}") sys.exit(1) # 执行合并 success = merge_images_with_chunks( args.input_dir, output_path=args.output, direction=args.direction, spacing=args.spacing, background=background ) if success: print("\n操作成功完成!") if SAFE_MODE: print("安全模式已启用 - 原始片未删除") else: print("\n操作失败,原始片保留") sys.exit(1) if __name__ == "__main__": main()这事我写的脚本现在这个功能只能处理单个文件我想让他处理多个文件我给他一个父目录他能按照现在处理单个文件逻辑去处理父文件下的所有文件
06-05
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值