用 Visual Studio 调试器中查看内存中图像

返回目录:OpenCV系列文章目录(持续更新中......)

前一篇:OpenCV4.9.0在windows系统下的安装

后一篇:  

​警告

本教程可以包含过时的信息。

Image Watch 是 Microsoft Visual Studio 的插件,可用于在调试应用程序时可视化内存中的图像(例如 cv::Mat 或 IplImage_ 对象)这有助于跟踪错误,或者简单地了解给定的代码段正在做什么

先决条件

本教程假定您具备以下条件:

  1. 安装了 Update 1 的Visual Studio 2012 Professional(或更高版本)。更新1可在此处下载。
  2. 在Windows计算机上安装OpenCV(教程:在 Windows 中安装)
  3. 能够在Visual Studio中创建和构建OpenCV项目(教程:如何在“Microsoft Visual Studio”中使用OpenCV构建应用程序)

安装

下载 Image Watch 安装程序。(Visual Studio 2019 |Visual Studio 2017 中文版 |Visual Studio 2012、2013、2015)安装程序位于扩展名为 .vsix(Visual Studio 扩展)的单个文件中。要启动它,只需双击Windows资源管理器中的 .vsix 文件。安装程序完成后,请确保重新启动 Visual Studio 以完成安装

例:

Image Watch适用于使用 OpenCV 图像对象(例如,cv::Mat)的任何现有项目。在此示例中,我们使用一个最小的测试程序,该程序从文件加载图像并运行边缘检测器。若要生成程序,请在 Visual Studio 中创建一个控制台应用程序项目,将其命名为“image-watch-demo”,并在下面插入源代码

​// Test application for the Visual Studio Image Watch Debugger extension
#include <iostream> // std::cout
#include <opencv2/core/core.hpp> // cv::Mat
#include <opencv2/imgcodecs/imgcodecs.hpp> // cv::imread()
#include <opencv2/imgproc/imgproc.hpp> // cv::Canny()
using namespace std;
using namespace cv;
void help()
{
cout
<< "----------------------------------------------------" << endl
<< "This is a test program for the Image Watch Debugger " << endl
<< "plug-in for Visual Studio. The program loads an " << endl
<< "image from a file and runs the Canny edge detector. " << endl
<< "No output is displayed or written to disk."
<< endl
<< "Usage:" << endl
<< "image-watch-demo inputimage" << endl
<< "----------------------------------------------------" << endl
<< endl;
}
int main(int argc, char *argv[])
{
help();
if (argc != 2)
{
cout << "Wrong number of parameters" << endl;
return -1;
}
cout << "Loading input image: " << argv[1] << endl;
Mat input;
input = imread(argv[1], IMREAD_COLOR);
cout << "Detecting edges in input image" << endl;
Mat edges;
Canny(input, edges, 10, 100);
return 0;
}

确保活动解决方案配置(内部版本 –> Configuration Manager)设置为调试版本(通常称为“调试”)。这应该会禁用编译器优化,以便调试器中的查看变量可以可靠地工作

生成解决方案(“生成 >生成解决方案”,或按 F7

在继续之前,不要忘记将输入图像的命令行参数添加到项目中(右键单击项目 –> 属性 –> 配置属性 –>调试,然后使用图像的位置设置字段命令参数)

现在在源行上设置一个断点,上面写着Mat edges;

若要设置断点,请右键单击源行,然后从上下文菜单中选择“断点 –>插入断点”

在调试器中启动程序(Debug –> Start Debugging,或按 F5)。命中断点时,程序将暂停,Visual Studio 会在断点处显示黄色指令指针:

breakpoint.png

现在,您可以检查程序的状态。例如,您可以打开“局部变量”窗口(“调试”>“Windows ”–“>局部变量”),该窗口将显示当前作用域中变量的名称和值:

vs_locals.png

​请注意,内置的“局部变量”窗口将仅显示文本。这就是 Image Watch 插件的用武之地。Image Watch 就像另一个 Locals 窗口,但内置了一个图像查看器。若要调出“图像监视”,请选择“视图”->“其他窗口”->“图像监视”。与 Visual Studio 的“局部变量”窗口一样,Image Watch 可以停靠到 Visual Studio IDE。此外,Visual Studio 还会记住你是否打开了图像监视,以及它在调试会话之间的位置。这意味着您只需执行一次此操作 - 下次开始调试时,Image Watch 将返回到您离开的位置。下面是停靠的 Image Watch 窗口在断点处的样子:

toolwindow.jpg

左上角的单选按钮 (Locals/Watch) 选择下面的图像列表中显示的内容:Locals 列出当前范围内的所有 OpenCV 图像对象(此列表会自动填充)。监视显示已固定以进行连续检查的图像表达式(此处未介绍,有关详细信息,请参阅图像监视文档)。图像列表显示基本信息,例如宽度、高度、通道数以及缩略图(如果可用)。在我们的示例中,图像列表包含我们的两个局部图像变量,即输入边缘

如果图像有缩略图,左键单击该图像将在右侧的图像查看器中选择该图像进行详细查看。查看器允许您平移(拖动鼠标)和缩放(鼠标滚轮)。它还显示当前鼠标位置的像素坐标和值。

viewer.jpg

请注意,列表中的第二张图像“边缘”显示为“无效”。这表示此图像对象的某些数据成员具有损坏或无效的值(例如,负图像宽度)。这在程序的这一点上是预期的,因为边缘的C++构造函数尚未运行,因此其成员具有未定义的值(在调试模式下,它们通常填充“0xCD”字节)。

从这里,您可以单步执行代码(Debug->Step Over,或按 F10)并观察像素变化:如果单步执行一次,则 Mat edges; 语句,边缘图像将从“invalid”变为“empty”,这意味着它现在处于有效状态(默认构造),即使它尚未初始化(使用 cv::例如,Mat::create())。如果在 cv::Canny() 调用上再执行一步,您将看到边缘图像的缩略图出现在图像列表中。

现在假设你想对 cv::Canny() 实现进行可视化健全性检查。通过在“图像列表”中选择边缘图像,将边缘图像带入查看器,并放大到具有明确定义边缘的区域:

edges_zoom.png

右键单击图像查看器以调出视图上下文菜单并启用链接视图(菜单项旁边的复选框指示是否启用该选项)。

viewer_context_menu.png

“链接视图”功能在相同大小的图像之间切换时使视图区域保持固定。要查看其工作原理,请从图像列表中选择输入图像 - 您现在应该在输入图像中看到相应的放大区域:

input_zoom.png

​您还可以使用向上/向下光标键在查看输入和边缘之间来回切换。这样,您就可以轻松验证检测到的边缘是否与输入图像中的数据很好地对齐。

更多 ...

Image Watch 具有许多更高级的功能,例如

  1. 将映像固定到监视列表,以便跨作用域或调试会话之间进行检查
  2. 直接在“监视”窗口内对图像进行钳位、阈值设置或差异
  3. 将内存中映像与文件中的参考映像进行比较

有关详细信息,请参阅在线图像监视文档 - 您也可以通过单击图像监视窗口中的帮助链接访问文档页面:

help_button.jpg

 参考文献: 

《Image Watch: viewing in-memory images in the Visual Studio debugger 》Wolf Kienzle

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

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

相关文章

Webapi(.net6) 批量服务注册

如果不考虑第三方库&#xff0c;如Autofac这种进行服务注入&#xff0c;通过本身的.Core Weabpi实现的&#xff0c;总结了两种实现方法&#xff0c; 1.一种是参考abp框架里面的形式; 1.1 新建个生命周期的文件夹: 三个接口分别为: public interface IScopedDependency { }pu…

tomcat 实现会话绑定

Tomcat 后端服务器实现 Session ID会话保持 基础架构&#xff1a; 7-6 代理服务器nginx配置 7-3 tomcat 服务器 7-5 同理 测试&#xff1a; 此时刷新&#xff0c;会话ID一直在变&#xff0c;这样不好 如何解决呢&#xff1f; 不好的是确定ip之后&#xff0c;会一直在一台机上…

RISC-V 编译环境搭建:riscv-gnu-toolchain 和 riscv-tools

RISC-V 编译环境搭建&#xff1a;riscv-gnu-toolchain 和 riscv-tools 编译环境搭建以及说明 操作系统&#xff1a;什么系统都可以 虚拟机&#xff1a;VMmare Workstation Pro 17.50.x (版本不限) 编译环境&#xff1a;Ubuntu 18.04.5 CPU&#xff1a;i7-8750h(虚拟机分配4核…

JVM学习-JMM

目录 1.什么是JMM 2.JMM怎样保障数据的可见性、有序性、原子性 2.1保证原子性 2.2.保证可见性 2.3保证有序性 3.CAS 3.1乐观锁和悲观锁 3.2 CAS介绍 4.重量级锁的自旋优化 1.什么是JMM JMM即Java内存模型 &#xff0c;定义了一套在多线程读写共享数据&#xff08;如数组、成…

openssl3.2 - note - Writing OpenSSL Provider Skeleton

文章目录 openssl3.2 - note - Writing OpenSSL Provider Skeleton概述笔记测试工程的建立复现的provider工程总结Provider包含的头文件openssl/core.h中的数据结构实现 OSSL_provider_init()看一下openssl自带的提供者provider的openssl命令行测试provider的本质是hook了opens…

插入排序:一种简单而有效的排序算法

插入排序&#xff1a;一种简单而有效的排序算法 一、什么是插入排序&#xff1f;二、插入排序的步骤三、插入排序的C语言实现四、插入排序的性能分析五、插入排序的优化六、总结 在我们日常生活和工作中&#xff0c;排序是一种非常常见的操作。比如&#xff0c;我们可能需要对一…

【 c 语言 】指针入门

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;C语言 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进步&…

ChatGPT编程—实现小工具软件(文件查找和筛选)

ChatGPT编程—实现小工具软件(文件查找和筛选) 今天借助[小蜜蜂AI][https://zglg.work]网站的ChatGPT编程实现一个功能&#xff1a;根据特定需求结合通配符和其他条件来进行文件查找和筛选。在这个例子中&#xff0c;我们将创建一个函数find_files&#xff0c;它接受用户输入的…

RK3568平台开发系列讲解(基础篇)内核是如何发送事件到用户空间

🚀返回专栏总目录 文章目录 一、相关接口函数二、udevadm 命令三、实验沉淀、分享、成长,让自己和他人都能有所收获!😄 一、相关接口函数 kobject_uevent 是 Linux 内核中的一个函数, 用于生成和发送 uevent 事件。 它是 udev 和其他设备管理工具与内核通信的一种方式。…

设计模式学习笔记 - 规范与重构 - 8.实践:程序出错返回啥?NULL、异常、错误吗、空对象?重构ID生成器,处理各函数的异常

概述 我们可以把函数的运行结果分为两类。一类是预期结果&#xff0c;也就是正常情况下输出的结果。一类是非预期的结果&#xff0c;也就是函数在异常&#xff08;或出错&#xff09;情况下输出的结果。 在正常情况下&#xff0c;函数返回数据的类型非常明确&#xff0c;但是…

【Spring Boot】创建你的第一个 Spring Boot 应用

创建你的第一个 Spring Boot 应用 1.环境配置2.步骤详解3.项目结构分析3.1 入口类 DemoApplication3.2 控制器 PathVariableController3.3 控制器 BasicController3.4 模型 User 4.运行 Spring Boot 目前已经成为了 Java 开发领域的框架范式。本篇博客&#xff0c;我将带领大家…

layui table列表重载后保持进度条位置不变

使用layui的table表格组件时&#xff0c;当我们操作了某行的修改后&#xff0c;刷新了页面&#xff0c;进度条则跳回到最上面。 除了layui高版本应该内置有方法解决了此问题&#xff0c;但是低版本需要另外想办法解决。 具体解决方式如下&#xff1a; 1.在编辑操作成功前&am…

【List、Set、数据结构、Collections】-Collections

day03 【List、Set、数据结构、Collections】 5.3 简述Comparable和Comparator两个接口的区别。 Comparable&#xff1a;强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序&#xff0c;类的compareTo方法被称为它的自然比较方法。只能在类中实现compareTo…

【Linux的 yum_vim工具篇】

Linux学习笔记---004 Linux的yum_vim工具篇1、Linux软件包管理器yum1.1、yum是什么&#xff1f;1.2、软件包是什么&#xff1f;软件包是谁给提供的呢&#xff1f;1.3、Linux系统(其中的centos 7)生态 2、yum的相关操作2.1、yum基本指令格式2.2、软件源 3、yum的本地配置3.1、配…

Lua-Lua与C++的交互2

Lua与C的交互是指在C程序中使用Lua本语言&#xff0c;或者在Lua脚本中调用C代码的过程。这种交互可以实现C与Lua之间的数据传递和函数调用。 在C中与Lua交互的主要步骤如下&#xff1a; 引入Lua库&#xff1a;首先需要在C程序中引入Lua的头文件和库文件&#xff0c;以便能够使…

pytorch中张量变换函数

在PyTorch中view(), transpose() 和 permute() 函数都是用于改变张量&#xff08;Tensor&#xff09;维度结构的&#xff0c;但它们的作用和使用场景有所不同。 torch.view() 功能&#xff1a;该函数用于将一个张量重塑为新的形状&#xff0c;但它必须保持原有元素数量不变。它…

【MASM汇编语言快速入门】8086MASM汇编深入理解指令对标志位的影响

8086MASM汇编深入理解指令对标志位的影响 文章目录 8086MASM汇编深入理解指令对标志位的影响0. 指令对标志位影响1. 指令对标志位影响速查表2. flags标志寄存器: 标志位含义解读flags1. 状态标志cf, pf, af, zf, sf, of2. 控制标志df, if, tf 详解&#xff1a;1. 传送指令2. 算…

如何在IDEA 中设置背景图片

在IDEA 中设置背景图片&#xff0c;可以按照以下步骤操作&#xff1a; 1、打开 IntelliJ IDEA 软件&#xff0c;进入代码编辑主界面。 点击编辑窗口上方的“File”菜单项。 2、在下拉子菜单中&#xff0c;选择“Settings”选项&#xff08;如果你使用的是 macOS&#xff0c;可…

AUTOSAR汽车电子嵌入式编程精讲300篇-车载 CAN 总线延时特性分析及优化(续)

目录 3.1.2 通信错误恢复时间 3.2 延时指标研究 3.2.1 总线 Burst 情况 3.2.2 抖动

vue3子父组件之间的调用

子组件&#xff1a; capacityIndex.vue 父组件&#xff1a; index.vue A.子组件获取父组件属性 1.在父组件中引用子组件 import capacityIndex from "./capacityIndex"; <capacityIndex :tankInfo"tankInfo" :deviceNameInfo"deviceNameInfo…