图像处理:预览并绘制图像细节
前言
因为最近在搞毕业论文的事情,要做出一下图像细节对比图,所以我这里写了两个脚本,一个用于框选并同时预览图像放大细节,可显示并返回框选图像的坐标,另外一个是输入框选图像的坐标并将放大的细节放置在图像中,效果如下所示:
效果也是相当不错的,好了咱们也不必多说,就是教会大家怎么使用这两个脚本就可以了。
框选图像并预览放大细节
我们这里写了一个图像区域的选择工具,主要是选择好图像路径,框选和文字的颜色,以及放大的倍数,此处放大的倍数仅用于查看,所以不用担心最后的效果。
import cv2def select_roi_region(image_path, line_color=(0, 255, 0), zoom_factor=3):drawing = Falseix, iy = -1, -1x, y, w, h = 0, 0, 0, 0img = cv2.imread(image_path)clone = img.copy()# 鼠标回调函数def mouse_callback(event, cur_x, cur_y, flags, param):nonlocal ix, iy, drawing, x, y, w, hif event == cv2.EVENT_LBUTTONDOWN:drawing = Trueix, iy = cur_x, cur_yx, y, w, h = 0, 0, 0, 0elif event == cv2.EVENT_MOUSEMOVE and drawing:temp_img = clone.copy()cv2.rectangle(temp_img, (ix, iy), (cur_x, cur_y), line_color, 2)x1, y1 = min(ix, cur_x), min(iy, cur_y)x2, y2 = max(ix, cur_x), max(iy, cur_y)if x2 > x1 and y2 > y1:try:roi = img[y1:y2, x1:x2]if roi.size > 0:enlarged = cv2.resize(roi, None, fx=3, fy=3,interpolation=cv2.INTER_CUBIC)cv2.imshow("Enlarged Preview", enlarged)except Exception as e:passcur_w = abs(cur_x - ix)cur_h = abs(cur_y - iy)if cur_w > 0 and cur_h > 0:try:roi = img[y1:y2, x1:x2]enlarged = cv2.resize(roi, None, fx=zoom_factor, fy=zoom_factor,interpolation=cv2.INTER_CUBIC)cv2.imshow("Enlarged Preview", enlarged)except:passcv2.putText(temp_img, f"X:{x1} Y:{y1} W:{cur_w} H:{cur_h}",(10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, line_color, 2)cv2.imshow("Select ROI (SPACE=Clear | ENTER=Confirm)", temp_img)elif event == cv2.EVENT_LBUTTONUP:drawing = Falsex = min(ix, cur_x)y = min(iy, cur_y)w = abs(cur_x - ix)h = abs(cur_y - iy)cv2.rectangle(clone, (x, y), (x + w, y + h), line_color, 2)cv2.putText(clone, f"X:{x} Y:{y} W:{w} H:{h}", (10, 30),cv2.FONT_HERSHEY_SIMPLEX, 0.7, line_color, 2)cv2.imshow("Select ROI (SPACE=Clear | ENTER=Confirm)", clone)cv2.namedWindow("Select ROI (SPACE=Clear | ENTER=Confirm)")cv2.setMouseCallback("Select ROI (SPACE=Clear | ENTER=Confirm)", mouse_callback)while True:cv2.imshow("Select ROI (SPACE=Clear | ENTER=Confirm)", clone)key = cv2.waitKey(1) & 0xFF# 空格键:清除选择if key == 32:clone = img.copy()ix, iy = -1, -1x, y, w, h = 0, 0, 0, 0try:cv2.destroyWindow("Enlarged Preview") if cv2.getWindowProperty("Enlarged Preview", 0) >=0 else Noneexcept:passcv2.imshow("Select ROI (SPACE=Clear | ENTER=Confirm)", clone)# 回车键:确认选择if key == 13:try:cv2.destroyWindow("Enlarged Preview")except:passbreakcv2.destroyAllWindows()print(f"Final selection - X:{x} Y:{y} W:{w} H:{h}")return (x, y, w, h)if __name__=="__main__":select_roi_region(r'E:\PythonProject\img_processing_techniques_main\Enlarge_local_details\images\781.png'
)
下面是我们的这个使用效果:
有一点问题就是在绘制好图像后再选框就会将文字遮挡住:
但是我们是提供了清楚键的,你只需要按下空格键就可以将全图的文字和框清理掉了,最后选择好合适的区域后,按下Enter键确定你框选的区域,以便进行下一步操作。
这里返回的坐标是(x,y,w,h),这种方式便于我们控制起始点和框的大小。
框选图像并放置放大细节
这里需要的是选择图像路径,框选的坐标,也提供放置位置的坐标,放大的系数,线条的颜色,宽度,以及是否绘制箭头。
如果你不提供放置的位置也可以,我们提供了一种自动计算位置的方法,主要就是比较框选区域的位置,然后计算出其对角线位置返回坐标。
import math
from PIL import Image, ImageDraw, ImageTkdef plot_highlight_region(image_path, region_to_zoom, paste_position=None, zoom_factor=3,line_color="red", line_wide=2, show_arrow=True, arrow_size=5):x, y, w, h = region_to_zoomimg = Image.open(image_path).convert("RGB")img_w, img_h = img.sizeoriginal_copy = img.copy()zoomed_w = int(w * zoom_factor)zoomed_h = int(h * zoom_factor)cropped = original_copy.crop((x, y, x + w, y + h))zoomed = cropped.resize((zoomed_w, zoomed_h), Image.Resampling.LANCZOS)if paste_position is None:if x + w < img_w / 2:paste_x = img_w - zoomed_welse:paste_x = 0if y + h < img_h / 2:paste_y = img_h - zoomed_helse:paste_y = 0paste_x = max(0, min(paste_x, img_w - zoomed_w))paste_y = max(0, min(paste_y, img_h - zoomed_h))paste_position = (paste_x, paste_y)img.paste(zoomed, paste_position)draw = ImageDraw.Draw(img)draw.rectangle([(x, y), (x + w, y + h)],outline=line_color,width=line_wide)paste_x, paste_y = paste_positiondraw.rectangle([paste_position,(paste_x + zoomed_w, paste_y + zoomed_h)],outline=line_color, width=line_wide)if show_arrow:def get_side_center(rect, side):x, y, w, h = rectreturn {'left': (x, y + h // 2),'right': (x + w, y + h // 2),'top': (x + w // 2, y),'bottom': (x + w // 2, y + h)}[side]src_rect = (x, y, w, h)dst_rect = (paste_position[0], paste_position[1], zoomed_w, zoomed_h)dx = (dst_rect[0] + zoomed_w / 2) - (x + w / 2)dy = (dst_rect[1] + zoomed_h / 2) - (y + h / 2)if abs(dx) > abs(dy):src_side = 'right' if dx > 0 else 'left'dst_side = 'left' if dx > 0 else 'right'else:src_side = 'bottom' if dy > 0 else 'top'dst_side = 'top' if dy > 0 else 'bottom'start_point = get_side_center(src_rect, src_side)end_point = get_side_center(dst_rect, dst_side)draw.line([start_point, end_point], fill=line_color, width=line_wide)arrow_size = line_wide * arrow_sizeangle = math.atan2(end_point[1] - start_point[1], end_point[0] - start_point[0])p1 = (end_point[0] - arrow_size * math.cos(angle - math.pi / 6),end_point[1] - arrow_size * math.sin(angle - math.pi / 6))p2 = (end_point[0] - arrow_size * math.cos(angle + math.pi / 6),end_point[1] - arrow_size * math.sin(angle + math.pi / 6))draw.polygon([end_point, p1, p2], fill=line_color)return imgif __name__ == "__main__":# 定义要放大的区域 (x, y, width, height)region_to_zoom = (256, 250, 50, 70)im_path = r'E:\PythonProject\img_processing_techniques_main\Enlarge_local_details\gtimage\781.png'im = plot_highlight_region(im_path, region_to_zoom)im.save("output.png")
我们先来看看,提供了放置坐标的效果:
if __name__ == "__main__":# 定义要放大的区域 (x, y, width, height)region_to_zoom = (256, 250, 50, 70)im_path = r'E:\PythonProject\img_processing_techniques_main\Enlarge_local_details\gtimage\861.png'im = plot_highlight_region(im_path, region_to_zoom, (22, 22))im.save("output.png")
自动计算的效果:
if __name__ == "__main__":# 定义要放大的区域 (x, y, width, height)region_to_zoom = (22, 22, 50, 70)im_path = r'E:\PythonProject\img_processing_techniques_main\Enlarge_local_details\gtimage\861.png'im = plot_highlight_region(im_path, region_to_zoom)im.save("output.png")
当然这里的自动计算还只是四个角。目前来说也算足够了。
关闭箭头的效果:
if __name__ == "__main__":# 定义要放大的区域 (x, y, width, height)region_to_zoom = (300, 250, 50, 70)im_path = r'E:\PythonProject\img_processing_techniques_main\Enlarge_local_details\gtimage\861.png'im = plot_highlight_region(im_path, region_to_zoom, show_arrow=False)im.save("output.png")
总结
如果只需要画框那么直接用下面的简略版本即可:
def highlight_region(image_path, region_to_zoom, line_color="red", line_wide=2):x, y, w, h = region_to_zoomimg = Image.open(image_path).convert("RGB")img_copy = img.copy()draw = ImageDraw.Draw(img)draw.rectangle([(x, y), (x + w, y + h)],outline=line_color,width=line_wide)return img
我们将前面的两个脚本组合在一起,便于我们更好的观察
if __name__ == "__main__":# 定义要放大的区域 (x, y, width, height)from mouse import select_roi_regionim_path = r'E:\PythonProject\img_processing_techniques_main\Enlarge_local_details\gtimage\861.png'region_to_zoom = select_roi_region(im_path)im = plot_highlight_region(im_path, region_to_zoom, show_arrow=False)im.save("output.png")
这里会先运行预选框程序,等按下Enter键之后会直接返回坐标。
我们的图像就生成好了:
写完这篇我还得继续去画图了。
相关文章:

图像处理:预览并绘制图像细节
前言 因为最近在搞毕业论文的事情,要做出一下图像细节对比图,所以我这里写了两个脚本,一个用于框选并同时预览图像放大细节,可显示并返回框选图像的坐标,另外一个是输入框选图像的坐标并将放大的细节放置在图像中&…...

力扣热题——最长相邻不相等子序列 |
题目要求从字符串数组 words 中选出一个最长的子序列,使得该子序列中相邻字符串对应的 groups 数组中的值不同。通过贪心算法,可以高效地解决该问题。具体步骤为:初始化一个结果列表,遍历 words 数组,检查当前字符串的…...
【抽丝剥茧知识讲解】引入mybtis-plus后,mapper实现方式
目录 前言一、传统 Mapper 接口方式二、继承 BaseMapper 的方式三、自定义通用 Mapper 的方式四、使用 MyBatis-Plus 的 ActiveRecord 模式五、使用 MyBatis-Plus 的 IService 接口六、使用建议 前言 mapper文件,作为Mybatis框架中定义SQL语句和映射关系的配置文件&…...

ssti刷刷刷
[NewStarCTF 公开赛赛道]BabySSTI_One 测试发现过滤关键字,但是特殊符号中括号、双引号、点都能用 可以考虑拼接或者编码,这里使用拼接 ?name{{()["__cla"~"ss__"]}}?name{{()["__cla"~"ss__"]["__ba&…...

java+selenum专题(一)
环境搭建部署篇-> 1.简介 java版的selenium,介绍一下java selenium自动化测试。大致和pythonselenium自动化测试差不多。基于java和selenium做自动化测试,因此你必须会搭建基本的开发环境,掌握python基本的语法和一个IDE来进行开发&…...
物体雅克比、空间雅克比、解析雅克比、几何雅克比
在机器人学中,雅可比矩阵是连接广义坐标速度与末端执行器速度的关键工具。根据应用场景和参考系的不同,雅可比矩阵可分为物体雅可比(Body Jacobian)、空间雅可比(Space Jacobian)、解析雅可比(A…...

[逆向工程]DebugView捕获WPS日志?解析未运行WPS时Shell扩展加载的原因与解决方案(二十五)
[逆向工程]DebugView捕获WPS日志?解析未运行WPS时Shell扩展加载的原因与解决方案(二十五) 引言:一个“幽灵”般的日志问题 你是否在使用 DebugView 排查系统问题时,发现日志中频繁出现 WPS 相关模块(如 k…...

ACM模式用Scanner和System.out超时的解决方案和原理
Hi~!这里是奋斗的明志,很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~~ 🌱🌱个人主页:奋斗的明志 🌱🌱所属专栏:笔试强训 📚本系列文章为个人学…...

Java注解详解:从入门到实战应用篇
1. 引言 Java注解(Annotation)是JDK 5.0引入的一种元数据机制,用于为代码提供附加信息。它广泛应用于框架开发、代码生成、编译检查等领域。本文将从基础到实战,全面解析Java注解的核心概念和使用场景。 2. 注解基础概念 2.1 什…...

QML 属性动画、行为动画与预定义动画
目录 引言相关阅读本文使用的动画属性工程结构示例解析示例1:属性动画应用示例2:行为动画实现示例3:预定义动画 总结工程下载 引言 QML动画系统为界面元素提供了流畅的过渡效果。本文通过三个示例,结合属性动画(PropertyAnimatio…...

window nvidia-smi命令 Failed to initialize NVML: Unknown Error
如果驱动目录下的可以执行,那可能版本原因 "C:\Program Files\NVIDIA Corporation\NVSMI\nvidia-smi"复制"C:\Program Files\NVIDIA Corporation\NVSMI\nvidia-smi.exe"替换 C:\Windows\System32\nvidia-smi.exe 或者 把C:\Windows\System3…...

自学嵌入式 day19-数据结构 链表
二、线性表的链式存储 1.特点: (1)线性表链式存储结构的特点是一组任意的存储单位存储线性表的数据元素,存储单元可以是连续的,也可以不连续。可以被存储在任意内存未被占用的位置上。 (2)所以…...

东芝第3代SiC MOSFET助于降低应用中电源损耗
功率器件是管理和降低各种电子设备电能功耗以及实现碳中和社会的重要元器件。由于与比硅材料相比,碳化硅具有更高的电压和更低的损耗,因此碳化硅(SiC)被广泛视为下一代功率器件的材料。虽然碳化硅功率器件目前主要用于列车逆变器&…...
Vue 2.0学习
个人简介 👨💻个人主页: 魔术师 📖学习方向: 主攻前端方向,正逐渐往全栈发展 🚴个人状态: 研发工程师,现效力于政务服务网事业 🇨🇳人生格言&…...
Mendix 中的XPath 令牌(XPath Tokens)详解
在 Mendix 中,XPath 令牌(XPath Tokens) 是一种特殊的动态参数化查询技术,允许你在 XPath 表达式中使用变量或上下文相关的值,从而实现更灵活的查询逻辑。 1. 什么是 XPath 令牌? XPath 令牌是 Mendix 提…...
Spring Batch学习,和Spring Cloud Stream区别
Spring Batch学习,和Spring Cloud Stream区别 1. 使用Spring Initializr创建项目2. 使用步骤构建作业(Chunk 模式)🧩 场景说明🧰 1. 示例目录结构📄 2. 创建输入文件(users.csv)&…...
【技术原理】Linux 文件时间属性详解:Access、Modify、Change 的区别与联系
在 Linux 系统中,每个文件都有三个核心时间属性:Access Time (atime)、Modify Time (mtime) 和 Change Time (ctime)。它们分别记录文件不同维度的变更信息,以下是具体区别与联系: 一、定义与触发条件 时间属性定义触发条件示例A…...
k8s之LoadBalancer Service 解析
Kubernetes LoadBalancer Service 解析:IP与端口详解 服务类型与IP解析 Service 是 Kubernetes 中的资源类型,用来将一组 Pod 的应用作为网络服务公开。每个 Pod 都有自己的 IP,但是这个 IP 的生命周期与 Pod 生命周期一致,也就…...
Vue3项目使用ElDrawer后select方法不生效
Vue3 项目中 ElDrawer 内 ElSelect 下拉框 z-index 失效问题分析与解决方案 问题描述问题分析解决方案结论 问题描述 在 Vue3 项目中使用 Element Plus 的 ElDrawer 组件时,当在抽屉内部使用 ElSelect 组件,发现下拉选择框(dropdownÿ…...

PD 分离推理的加速大招,百度智能云网络基础设施和通信组件的优化实践
为了适应 PD 分离式推理部署架构,百度智能云从物理网络层面的「4us 端到端低时延」HPN 集群建设,到网络流量层面的设备配置和管理,再到通信组件和算子层面的优化,显著提升了上层推理服务的整体性能。 百度智能云在大规模 PD 分离…...

官方 Elasticsearch SQL NLPChina Elasticsearch SQL
官方的可以在kibana 控制台上进行查询: POST /_sql { “query”: “SELECT client_ip, status FROM logs-2024-05 WHERE status 500” } NLPChina Elasticsearch SQL就无法以在kibana 控制台上进行查询,但是可以使用postman接口进行查询:...

5月16日复盘-目标检测开端
5月16日复盘 一、图像处理之目标检测 1. 目标检测认知 Object Detection,是指在给定的图像或视频中检测出目标物体在图像中的位置和大小,并进行分类或识别等相关任务。 目标检测将目标的分割和识别合二为一。 What、Where 2. 使用场景 目标检测用于…...
读取toml, 合并,生成新文件
依次读取三个TOML文件并合并,后续文件覆盖之前的值,最终将结果写入新文件 import toml def deep_update(base_dict, update_dict): """ 递归合并字典,后续字典的值覆盖前者[6] """ for key, …...

mathematics-2024《Graph Convolutional Network for Image Restoration: A Survey》
推荐深蓝学院的《深度神经网络加速:cuDNN 与 TensorRT》,课程面向就业,细致讲解CUDA运算的理论支撑与实践,学完可以系统化掌握CUDA基础编程知识以及TensorRT实战,并且能够利用GPU开发高性能、高并发的软件系统…...

IDEA怎么汉化idea中文改回英文版
第一步:点击左上角的File,然后选择Setting 第二步:Setting页面选择 Appearance & Behavior,然后展开System Settings,然后选择 Language and Region,进行修改 我操作的是2024年的版本 File->Settings -> Ap…...
Android minSdk从21升级24后SO库异常
问题 minSdk从21调整到24后: java.nio.file.NoSuchFileException: /data/app/~~Z9s2NfuDdclOUwUBLKnk0A/com.rs.unity- Bg31QvFwF4qsCwv2XCqT-w/split_config.arm64_v8a.apkjava.nio.file.NoSuchFileException: /data/app/~~Z9s2NfuDdclOUwUBLKnk0A/com.rs.unity-…...

车道线检测----CLRKDNet
今天的最后一篇 车道线检测系列结束 CLRKDNet:通过知识蒸馏加速车道检测 摘要:道路车道是智能车辆视觉感知系统的重要组成部分,在安全导航中发挥着关键作用。在车道检测任务中,平衡精度与实时性能至关重要,但现有方法…...

从技术视角解构 Solana Meme 币生态
在高吞吐、高并发的 Solana 网络上,一类轻量化、高热度的代币形式正在爆发式增长——Meme Token(迷因代币)。尽管起源于社群文化,但其技术实现并非“玩笑”,而是一整套构建于 Solana Runtime 与 Token Extensions 之上…...

智能接处警系统:以秒级联动响应重塑应急处置效能
随着我国能源、化工、航空等关键行业的快速发展,传统消防管理模式已难以满足高效应急响应的需求。国家能源局、应急管理部、民航总局均出台专项规定,对消防站建设提出更高要求,在此背景下,智能接处警系统正是应对这些挑战的核…...
OpenCV直方图与直方图均衡化
一、图像直方图基础 1. 什么是图像直方图? 图像直方图是图像处理中最基本且重要的统计工具之一,它用图形化的方式表示图像中像素强度的分布情况。对于数字图像,直方图描述了每个可能的像素强度值(0-255)在图像中出现…...