找到
2
篇与
Python
相关的结果
-
使用 Python NumPy 原生代码实现点云的体素下采样 在 3D 数据处理领域,点云是一种重要的空间信息表示形式,用于捕捉物体和环境的几何形状。然而,点云数据通常非常密集,包含数百万甚至更多的点,这对存储、处理和可视化都带来了挑战。为了解决这个问题,我们需要对点云进行下采样,以减少点的数量,同时尽量保留数据的整体结构。体素下采样(Voxel Downsampling)是一种高效的下采样方法,它通过将点云划分到三维网格(体素)中并对每个体素内的点进行平均来实现这一目标。 什么是体素下采样? 此部分内容需要付费后才能阅读 您当前未登录,游客身份购买的内容仅在当前浏览器生效 (7天)。 清除Cookie或更换设备后需重新购买。 为获得永久阅读权限, 建议注册账户 后购买。 支付 4.99 元阅读 请使用支付宝扫描二维码支付 金额:4.99 元 二维码2小时内有效,支付成功后页面将自动刷新 if(typeof payit_generate_qr === "undefined") { function payit_generate_qr(id, url, cid, price) { var container = document.getElementById(id); var qrContainer = container.querySelector(".payit-qrcode-container"); var qrCodeDiv = container.querySelector(".payit-qrcode"); var btn = container.querySelector(".payit-button"); btn.disabled = true; btn.innerText = "二维码生成中..."; var xhr = new XMLHttpRequest(); xhr.open("POST", url, true); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status === 200) { try { var res = JSON.parse(xhr.responseText); if(res.code === 0 && res.qr_code) { qrContainer.style.display = "block"; container.querySelector(".payit-mask").style.display = "none"; new QRCode(qrCodeDiv, { text: res.qr_code, width: 150, height: 150 }); payit_check_status(id, "https://www.hubtools.cn/payit/check", res.out_trade_no); } else { alert("二维码生成失败: " + (res.msg || "未知错误")); btn.disabled = false; btn.innerText = "支付 " + price + " 元阅读"; } } catch (e) { alert("从服务器获取数据时出错。"); btn.disabled = false; btn.innerText = "支付 " + price + " 元阅读"; } } else { alert("请求服务器失败。"); btn.disabled = false; btn.innerText = "支付 " + price + " 元阅读"; } } }; xhr.send("cid=" + cid + "&price=" + price); } } if(typeof set_payit_cookie === "undefined") { function set_payit_cookie(name, value, days) { var expires = ""; if (days) { var date = new Date(); date.setTime(date.getTime() + (days*24*60*60*1000)); expires = "; expires=" + date.toUTCString(); } document.cookie = name + "=" + (value || "") + expires + "; path=/"; } } if(typeof payit_check_status === "undefined") { function payit_check_status(id, url, order_id) { var interval = setInterval(function() { var xhr = new XMLHttpRequest(); xhr.open("POST", url, true); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.onreadystatechange = function() { if (xhr.readyState === 4 && xhr.status === 200) { try { var res = JSON.parse(xhr.responseText); if (res.code === 0) { clearInterval(interval); // 如果是游客,前端设置cookie if (res.token) { var cookieName = "payit_cid_" + res.cid; set_payit_cookie(cookieName, res.token, res.expire); } document.getElementById(id).innerHTML = "支付成功,正在刷新页面..."; setTimeout(function() { location.reload(); }, 200); } } catch (e) { /* 支付未成功,不处理 */ } } }; xhr.send("out_trade_no=" + order_id); }, 3000); } } .payit-wrapper { border: 2px dashed #e67e22; background-color: #fdf5ee; padding: 20px; text-align: center; margin: 20px 0; border-radius: 8px; } .payit-wrapper .payit-guest-notice { font-size: 13px; color: #555; background-color: rgba(0,0,0,0.03); border: 1px solid rgba(0,0,0,0.05); padding: 10px; margin: 15px auto; border-radius: 5px; max-width: 95%; line-height: 1.6; } .payit-wrapper .payit-guest-notice p { margin: 5px 0; } .payit-wrapper .payit-guest-notice a { color: #e67e22; font-weight: bold; text-decoration: none; } .payit-wrapper .payit-guest-notice a:hover { text-decoration: underline; } .payit-mask .payit-notice { font-size: 18px; color: #e67e22; font-weight: bold; margin-bottom: 15px; display: flex; align-items: center; justify-content: center; } .payit-mask .payit-button { background-color: #e67e22; color: #ffffff; border: none; padding: 12px 25px; font-size: 16px; cursor: pointer; border-radius: 5px; transition: opacity 0.2s; } .payit-mask .payit-button:hover { opacity: 0.9; } .payit-mask .payit-button:disabled { opacity: 0.6; cursor: not-allowed; } .payit-qrcode-container { color: #333; } .payit-qrcode-container p { margin: 10px 0; } .payit-qrcode { width: 150px; height: 150px; margin: 10px auto; padding: 5px; background: white; border: 1px solid #ddd; border-radius: 3px;} 代码实现 以下是一个完整的 Python 脚本,使用 NumPy 实现点云的体素下采样。代码简洁高效,适用于大多数基本的点云处理需求。 import numpy as np from collections import defaultdict def read_point_cloud(file_path): """读取点云文件,假设每行是一个点的xyz坐标,可能包含其他属性""" points = [] with open(file_path, 'r') as f: for line in f: parts = line.strip().split() if len(parts) >= 3: # 至少包含xyz三个坐标 x, y, z = map(float, parts[:3]) points.append([x, y, z]) return np.array(points) def voxel_downsample(points, voxel_size): """体素下采样""" # 创建体素网格 voxel_grid = defaultdict(list) # 计算每个点所在的体素 for point in points: voxel_coord = tuple((point // voxel_size).astype(int)) voxel_grid[voxel_coord].append(point) # 对每个体素内的点取平均 downsampled_points = [] for voxel_coord, voxel_points in voxel_grid.items(): if voxel_points: avg_point = np.mean(voxel_points, axis=0) downsampled_points.append(avg_point) return np.array(downsampled_points) def write_point_cloud(file_path, points): """将点云写入文件""" with open(file_path, 'w') as f: for point in points: f.write(f"{point[0]} {point[1]} {point[2]}\n") def main(): # 配置参数 input_file = "test1_pointcloud - Cloud.subsampled.txt" # 输入点云文件 output_file = "downsampled_test1_pointcloud - Cloud.subsampled.txt" # 输出点云文件 voxel_size = 1.2 # 体素大小,根据你的点云尺度调整 # 读取点云 points = read_point_cloud(input_file) print(f"原始点云数量: {len(points)}") # 体素下采样 downsampled_points = voxel_downsample(points, voxel_size) print(f"下采样后点云数量: {len(downsampled_points)}") # 保存下采样后的点云 write_point_cloud(output_file, downsampled_points) print(f"下采样后的点云已保存到: {output_file}") if __name__ == "__main__": main()体素大小的选择 体素大小(voxel_size)是下采样的关键参数,直接影响结果: 较大的体素大小:会导致更激进的下采样,点数减少更多,但可能会丢失细节。 较小的体素大小:保留更多细节,但下采样后的点云仍然较大。 选择合适的体素大小需要根据点云的尺度以及应用需求。例如,对于建筑扫描,1 厘米的体素大小可能合适;而对于室外大场景,1 米的体素大小可能更适合。 效果展示 左边是原始的点云,右边是体素下采样之后的点云。 下采样前后的对比图片 -
Python使用Pillow批量将tif/tiff图片转换为jpg/png 在日常图像处理工作中,TIFF格式因其高质量和支持多页等特性被广泛使用,但也存在文件体积大、兼容性差等问题。本文将介绍如何利用Python的Pillow库批量将TIFF图像转换为更通用的JPG或PNG格式,并提供带图形界面的转换工具。 为什么需要转换TIFF格式? 因为实在太大了,一张照片就占了十几MB。我一共有好几千张。 TIFF格式图片 此外,我还想变成灰度图。对于这样批量的任务,使用那些网页版本的转换器应该是不行的,不得不使用一个批量的脚本。 准备工作 其实主要使用了两个核心库,一个是pillow,一个是tkinter,tkinter是python的内置库。安装pillow即可: pip install Pillow -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple完整转换代码 import os from PIL import Image import tkinter as tk from tkinter import filedialog, messagebox def convert_tiff_to_image(input_folder, output_folder, output_format, convert_to_gray): """批量转换TIFF文件为指定格式,可选择灰度转换""" tiff_extensions = ('.tif', '.tiff') # 收集所有TIFF文件 tiff_files = [ f for f in os.listdir(input_folder) if os.path.splitext(f)[1].lower() in tiff_extensions ] if not tiff_files: messagebox.showwarning("警告", f"在目录中未找到TIFF文件:\n{input_folder}") return False # 确保输出目录存在 os.makedirs(output_folder, exist_ok=True) converted_count = 0 for filename in tiff_files: input_path = os.path.join(input_folder, filename) output_name = os.path.splitext(filename)[0] + f'.{output_format}' output_path = os.path.join(output_folder, output_name) try: with Image.open(input_path) as img: # 转换为灰度(如果需要) if convert_to_gray: img = img.convert('L') # 保存为指定格式 img.save(output_path) converted_count += 1 except Exception as e: print(f"转换失败: {filename} - {str(e)}") return converted_count def main(): """主函数:获取用户输入并执行转换""" root = tk.Tk() root.withdraw() # 设置输入文件夹 input_folder = filedialog.askdirectory(title="选择TIFF文件所在文件夹") if not input_folder: return # 设置输出文件夹 output_folder = filedialog.askdirectory(title="选择输出文件夹") if not output_folder: return # 选择输出格式 output_format = tk.simpledialog.askstring( "输出格式", "请输入输出格式 (jpg 或 png):", initialvalue="png" ) if not output_format or output_format.lower() not in ('jpg', 'png'): messagebox.showerror("错误", "输出格式必须是 'jpg' 或 'png'") return output_format = output_format.lower() # 选择是否转为灰度 convert_to_gray = messagebox.askyesno("灰度转换", "是否转换为灰度图像? (是/否)") # 执行转换 converted_count = convert_tiff_to_image( input_folder, output_folder, output_format, convert_to_gray ) if converted_count > 0: messagebox.showinfo( "完成", f"成功转换 {converted_count} 个文件!\n输出目录: {output_folder}" ) else: messagebox.showwarning("无文件转换", "没有文件被转换") if __name__ == "__main__": main()GUI交互流程 第一步:选择包含TIFF的源文件夹 第二步:选择输出目录 第三步:选择输出格式(JPG/PNG) 第四步:选择是否转为灰度图 GUI交互流程图片 最后就能再输出文件夹里获得自己想要的新格式图片了。