图像处理:预览并绘制图像细节

news2025/5/17 13:01:55

前言

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

效果也是相当不错的,好了咱们也不必多说,就是教会大家怎么使用这两个脚本就可以了。 

框选图像并预览放大细节

我们这里写了一个图像区域的选择工具,主要是选择好图像路径,框选和文字的颜色,以及放大的倍数,此处放大的倍数仅用于查看,所以不用担心最后的效果。

import cv2

def select_roi_region(image_path, line_color=(0, 255, 0), zoom_factor=3):
    drawing = False
    ix, iy = -1, -1
    x, y, w, h = 0, 0, 0, 0
    img = cv2.imread(image_path)
    clone = img.copy()
    # 鼠标回调函数
    def mouse_callback(event, cur_x, cur_y, flags, param):
        nonlocal ix, iy, drawing, x, y, w, h

        if event == cv2.EVENT_LBUTTONDOWN:
            drawing = True
            ix, iy = cur_x, cur_y
            x, y, w, h = 0, 0, 0, 0

        elif 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:
                    pass

            cur_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:
                    pass
            cv2.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 = False
            x = 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, -1
            x, y, w, h = 0, 0, 0, 0
            try:
                cv2.destroyWindow("Enlarged Preview") if cv2.getWindowProperty("Enlarged Preview", 0) >=0 else None
            except:
                pass
            cv2.imshow("Select ROI (SPACE=Clear | ENTER=Confirm)", clone)
        # 回车键:确认选择
        if key == 13:
            try:
                cv2.destroyWindow("Enlarged Preview")
            except:
                pass
            break
    cv2.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, ImageTk

def 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_zoom
    img = Image.open(image_path).convert("RGB")
    img_w, img_h = img.size
    original_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_w
        else:
            paste_x = 0
        if y + h < img_h / 2:
            paste_y = img_h - zoomed_h
        else:
            paste_y = 0
        paste_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_position
    draw.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 = rect
            return {
                '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_size
        angle = 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 img

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\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_zoom
    img = 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_region
    im_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键之后会直接返回坐标。

我们的图像就生成好了:

写完这篇我还得继续去画图了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2377678.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

力扣热题——最长相邻不相等子序列 |

题目要求从字符串数组 words 中选出一个最长的子序列&#xff0c;使得该子序列中相邻字符串对应的 groups 数组中的值不同。通过贪心算法&#xff0c;可以高效地解决该问题。具体步骤为&#xff1a;初始化一个结果列表&#xff0c;遍历 words 数组&#xff0c;检查当前字符串的…

ssti刷刷刷

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

java+selenum专题(一)

环境搭建部署篇-> 1.简介 java版的selenium&#xff0c;介绍一下java selenium自动化测试。大致和pythonselenium自动化测试差不多。基于java和selenium做自动化测试&#xff0c;因此你必须会搭建基本的开发环境&#xff0c;掌握python基本的语法和一个IDE来进行开发&…

[逆向工程]DebugView捕获WPS日志?解析未运行WPS时Shell扩展加载的原因与解决方案(二十五)

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

ACM模式用Scanner和System.out超时的解决方案和原理

Hi~&#xff01;这里是奋斗的明志&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f331;&#x1f331;个人主页&#xff1a;奋斗的明志 &#x1f331;&#x1f331;所属专栏&#xff1a;笔试强训 &#x1f4da;本系列文章为个人学…

Java注解详解:从入门到实战应用篇

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

QML 属性动画、行为动画与预定义动画

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

window nvidia-smi命令 Failed to initialize NVML: Unknown Error

如果驱动目录下的可以执行&#xff0c;那可能版本原因 "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.特点&#xff1a; &#xff08;1&#xff09;线性表链式存储结构的特点是一组任意的存储单位存储线性表的数据元素&#xff0c;存储单元可以是连续的&#xff0c;也可以不连续。可以被存储在任意内存未被占用的位置上。 &#xff08;2&#xff09;所以…

东芝第3代SiC MOSFET助于降低应用中电源损耗

功率器件是管理和降低各种电子设备电能功耗以及实现碳中和社会的重要元器件。由于与比硅材料相比&#xff0c;碳化硅具有更高的电压和更低的损耗&#xff0c;因此碳化硅&#xff08;SiC&#xff09;被广泛视为下一代功率器件的材料。虽然碳化硅功率器件目前主要用于列车逆变器&…

PD 分离推理的加速大招,百度智能云网络基础设施和通信组件的优化实践

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

官方 Elasticsearch SQL NLPChina Elasticsearch SQL

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

5月16日复盘-目标检测开端

5月16日复盘 一、图像处理之目标检测 1. 目标检测认知 ​ Object Detection&#xff0c;是指在给定的图像或视频中检测出目标物体在图像中的位置和大小,并进行分类或识别等相关任务。 ​ 目标检测将目标的分割和识别合二为一。 ​ What、Where 2. 使用场景 目标检测用于…

mathematics-2024《Graph Convolutional Network for Image Restoration: A Survey》

推荐深蓝学院的《深度神经网络加速&#xff1a;cuDNN 与 TensorRT》&#xff0c;课程面向就业&#xff0c;细致讲解CUDA运算的理论支撑与实践&#xff0c;学完可以系统化掌握CUDA基础编程知识以及TensorRT实战&#xff0c;并且能够利用GPU开发高性能、高并发的软件系统&#xf…

IDEA怎么汉化idea中文改回英文版

第一步:点击左上角的File&#xff0c;然后选择Setting 第二步&#xff1a;Setting页面选择 Appearance & Behavior&#xff0c;然后展开System Settings&#xff0c;然后选择 Language and Region&#xff0c;进行修改 我操作的是2024年的版本 File->Settings -> Ap…

车道线检测----CLRKDNet

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

从技术视角解构 Solana Meme 币生态

在高吞吐、高并发的 Solana 网络上&#xff0c;一类轻量化、高热度的代币形式正在爆发式增长——Meme Token&#xff08;迷因代币&#xff09;。尽管起源于社群文化&#xff0c;但其技术实现并非“玩笑”&#xff0c;而是一整套构建于 Solana Runtime 与 Token Extensions 之上…

智能接处警系统:以秒级联动响应重塑应急处置效能

​​随着我国能源、化工、航空等关键行业的快速发展&#xff0c;传统消防管理模式已难以满足高效应急响应的需求。国家能源局、应急管理部、民航总局均出台专项规定&#xff0c;对消防站建设提出更高要求&#xff0c;在此背景下&#xff0c;智能接处警系统正是应对这些挑战的核…

GpuGeek 网络加速:破解 AI 开发中的 “最后一公里” 瓶颈

摘要&#xff1a; 网络延迟在AI开发中常被忽视&#xff0c;却严重影响效率。GpuGeek通过技术创新&#xff0c;提供学术资源访问和跨国数据交互的加速服务&#xff0c;助力开发者突破瓶颈。 目录 一、引言&#xff1a;当算力不再稀缺&#xff0c;网络瓶颈如何破局&#xff1f; …

C# DataGridView 选中所有复选框

问题描述 在程序中尝试选中所有复选框&#xff0c;但出现错误。如果单击顶部的完整选中/释放复选框&#xff0c;同时选中包含复选框的列&#xff0c;则选定区域不会改变。该如何解决&#xff1f; 上面的图片是点击完整版本之后的。 下面是本文的测试代码&#xff0c;函数 dat…