`

openCV入门----单窗口多图片显示

阅读更多
    在通过图像显示入门之后,自然想到多图像单窗口显示如何实现,有时候往往要对比几幅图来加以对比,从而更直观地看到处理效果!在Matlab里就很容易做了,如果是显示多个曲线图,那么subplot函数秒秒钟帮你解决问题!但是C++中使用openCV函数,那可能得费一点功夫了!
     话不多说,直接上代码!
#include<iostream>
#include <stdarg.h>
#include"windows.h"
#include"stdio.h"
#include"cv.h"
#include"highgui.h"
#include"cxcore.h"
using namespace std;
// 隐藏 console 窗口
//#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")

// 单窗口显示多幅图像的函数
void cvShowMultiImages(char* title, int nArgs, ...)
{
// img - Used for getting the arguments
IplImage* img;
// DispImage - the image in which all the input images are to be
//copied
IplImage* DispImage;

int size; // size - the size of the images in the window
int ind;  // ind - the index of the image shown in the window
int x, y;  // x,y - the coordinate of top left coner of input images
int w, h;    // w,h - the width and height of the image

// r - Maximum number of images in a column
// c - Maximum number of images in a row
int r, c;

// scale - How much we have to resize the image
float scale;
// max - Max value of the width and height of the image
int max;
// space - the spacing between images
int space;

// If the number of arguments is lesser than 0 or greater than 12
// return without displaying
if (nArgs <= 0) {
printf("Number of arguments too small..../n");
return;
}
else if (nArgs > 12) {
printf("Number of arguments too large..../n");
return;
}
// Determine the size of the image,
// and the number of rows/cols
// from number of arguments
else if (nArgs == 1) {
r = c = 1;
size = 300;
}
else if (nArgs == 2) {
r = 2; c = 1;
size = 300;
}
else if (nArgs == 3 || nArgs == 4) {
r = 2; c = 2;
size = 300;
}
else if (nArgs == 5 || nArgs == 6) {
r = 3; c = 2;
size = 200;
}
else if (nArgs == 7 || nArgs ==8 ) {
r = 4; c = 2;
size = 200;
}
else {
r = 4; c = 3;
size = 150;
}

// Create a new 3 channel image to show all the input images
DispImage = cvCreateImage(cvSize(60 + size*r, 20 + size*c), IPL_DEPTH_8U, 3);[0]
// Used to get the arguments passed
va_list args;[1]
va_start(args, nArgs);

// Loop for nArgs number of arguments
space = 20;
for (ind = 0, x = space, y = space; ind < nArgs; ind++, x += (space + size)) {

// Get the Pointer to the IplImage
img = va_arg(args, IplImage*);

// Check whether it is NULL or not
// If it is NULL, release the image, and return
if (img == 0) {
printf("Invalid arguments");
cvReleaseImage(&DispImage);
return;
}

// Find the width and height of the image
w = img->width;
h = img->height;

// Find whether height or width is greater in order to resize the image
max = (w > h) ? w : h;

// Find the scaling factor to resize the image
scale = (float)((float)max / size);

// Used to Align the images
// i.e. Align the image to next row
if (ind % r == 0 && x != space) {
x = space;
y += space + size;
}

               // Set the image ROI to display the current image
cvSetImageROI(DispImage, cvRect(x, y, (int)(w / scale), (int)(h / scale)));[2]
     // Resize the input image and copy the it to the Single Big Image
cvResize(img, DispImage);[3]
// Reset the ROI in order to display the next image
cvResetImageROI(DispImage);[4]
}

// Create a new window, and show the Single Big Image
//cvNamedWindow( title, 1 );
cvShowImage(title, DispImage);
// End the number of arguments
va_end(args);
// Release the Image Memory
cvReleaseImage(&DispImage);
}

int main()
{
/*   CvCapture *capture;*/
int i = 0;
IplImage* frame = cvLoadImage("8.png");
cvNamedWindow("video");
cvResizeWindow("video", 700, 660);
IplImage *frame_not = cvCreateImage(cvGetSize(frame), frame->depth, frame->nChannels);
cvNot(frame, frame_not);
IplImage *frame_gray = cvCreateImage(cvGetSize(frame), frame->depth, 1);
IplImage *frame1 = cvCreateImage(cvGetSize(frame), frame->depth, frame->nChannels);
IplImage *frame_canny = cvCreateImage(cvGetSize(frame), frame->depth, 1);
IplImage *frame2 = cvCreateImage(cvGetSize(frame), frame->depth, frame->nChannels);
cvCvtColor(frame, frame_gray, CV_RGB2GRAY);[5]
cvCvtColor(frame_gray, frame1, CV_GRAY2BGR);
cvCanny(frame_gray, frame_canny, 20, 75, 3);[6]
cvCvtColor(frame_canny, frame2, CV_GRAY2BGR);
cvShowMultiImages("video", 3, frame, frame_not, frame2);

cvWaitKey();

cvReleaseImage(&frame_not);
cvReleaseImage(&frame1);
cvReleaseImage(&frame_gray);
cvReleaseImage(&frame2);
cvReleaseImage(&frame_canny);

cvDestroyWindow("video");

return 0;
}

效果如下:




正如代码中红色部分所示,需要注意一下几个函数或者知识点:
[0]:cvCreateImage是openCV中的一个函数。     

cvCreateImage:创建头并分配数据
  IplImage* cvCreateImage( CvSize size, int depth, int channels );
  参数说明:
  size 图像宽、高.这里涉及到一个专门的类Cvsize(int h,int w).
  depth 图像元素的位深度,可以是下面的其中之一:
  IPL_DEPTH_8U - 无符号8位整型
  IPL_DEPTH_8S - 有符号8位整型
  IPL_DEPTH_16U - 无符号16位整型
  IPL_DEPTH_16S - 有符号16位整型
  IPL_DEPTH_32S - 有符号32位整型
  IPL_DEPTH_32F - 单精度浮点数
  IPL_DEPTH_64F - 双精度浮点数
  channels:
  每个元素(像素)通道号.可以是 1, 2, 3 或 4.通道是交叉存取的,例如通常的彩色图像数据排列是:b0 g0 r0 b1 g1 r1 ... 虽然通常 IPL 图象格式可以存贮非交叉存取的图像,并且一些OpenCV 也能处理他, 但是这个函数只能创建交叉存取图像.
[1]:va_list
这是C语言在解决函数多变量参数问题时定义的一组宏。由va_start()和va_end()界定。
    typedef char* va_list;
  void va_start ( va_list ap, prev_param );
  type va_arg ( va_list ap, type );
  void va_end ( va_list ap );
其中,va_list 是一个字符指针,可以理解为指向当前参数的一个指针,取参必须通过这个指针进行。
使用步骤如下:
    <Step 1> 在调用参数表之前,应该定义一个 va_list 类型的变量,以供后用(假设这个 va_list 类型变量被定义为ap);
    <Step 2> 然后对 ap 进行初始化,让它指向可变参数表里面的第一个参数。这是通过 va_start 来实现的,其第一个参数是 ap 本身,第二个参数是在变参表前面紧挨着的一个变量;
    <Step 3> 然后是获取参数,调用 va_arg。它的第一个参数是 ap,第二个参数是要获取的参数的指定类型,并返回这个指定类型的值,同时把 ap 的位置指向变参表的下一个变量位置;
    <Step 4> 获取所有的参数之后,我们有必要将这个 ap 指针关掉,以免发生危险,方法是调用 va_end。它是将输入的参数 ap 置为 NULL,应该养成获取完参数表之后关闭指针的习惯。
这还是比较抽象,那么上代码来解决问题吧!
#include<iostream>
#include <stdarg.h>
using namespace std;
/*
这是一个va_list测试函数
*/
int Sum(int n,...)//这里的n表示后面变量的参数,定界用
{
va_list ap;
va_start(ap, n);
int sum = 0;
for (int i = 0;i < n;i++)
{
sum = sum + va_arg(ap, int);
}
va_end(ap);
return sum;
}
int main()
{
cout << Sum(5, 1, 1, 1, 1, 1) << endl;
getchar();
}
我们定义了sum这个函数,想把若干数求和再输出来,那么sum中第一个参数便是你真正要输入的参数个数。最后这个程序运行的结果不言而喻:5.注意:va_list宏是包含在头文件stdarg.h中的,不要忘记了!
[2]:cvSetImageROI和cvRect函数
基于给定的矩形设置图像的ROI(感兴趣区域,region of interesting)大多数OpenCV函数都支持ROI,并将它作为一个独立图像进行处理,所有像素坐标都是从ROI的左上角或者左下角(基于图像结构)开始计算的。cvSetImageROI(img1,cvRect(100,100,356,156)),(100,100)表示ROI区域的左上角坐标,356,156分别表示ROI区域的长宽。
[3]:cvResize:
void cvResize( const CvArr* src, CvArr* dst, int interpolation=CV_INTER_LINEAR );
主要功能:重新调整图像src(或它的ROI),使它精确匹配目标dst(或其ROI)。这里需要说明的是,cvResize可以用来调整3通道图像(如RGB图像)和单通道图像的大小。
src: 源图像
dst :目标图像
interpolation 修改、插补的方法,取值如下:
·CV_INTER_NN - 最近-邻居插补
·CV_INTER_LINEAR - 双线性插值(默认方法)
·CV_INTER_AREA - 像素面积相关重采样。当缩小图像时,该方法可以避免波纹的出现。当放大图像时,类似于方法CV_INTER_NN。(It is the preferred method for image decimation that gives moire-free results. In case of zooming it is similar to CV_INTER_NN method. )
·CV_INTER_CUBIC - 双三次插值。
[4]:cvResetImageROI
功能: 释放基于给定的矩形设置图像的ROI(感兴趣区域,region of interesting)
格式: void cvResetImageROI(IplImage* image)
参数: image 图像头,待处理图像
说明: 释放图像image中被设定的感兴趣区域ROI,与cvSetImageROI相对应。相对应这点很重要!
[5]:cvCvtColor函数
void cvCvtColor( const CvArr* src, CvArr* dst, icvcvtcolor
cvcvtcolornt code );
src:输入的 8-bit,16-bit或 32-bit单倍精度浮点数影像名。
dst:输出的8-bit, 16-bit或 32-bit单倍精度浮点数影像。
code:色彩空间转换的模式,该code来实现不同类型的颜色空间转换。比如CV_BGR2GRAY表示转换为灰度图,CV_BGR2HSV将图片从RGB空间转换为HSV空间。其中当code选用CV_BGR2GRAY时,dst需要是单通道图片。当code选用CV_BGR2HSV时,对于8位图,需要将RGB值归一化到0-1之间。这样得到HSV图中的H范围才是0-360,S和V的范围是0-1,CV_RGB2Lab转换RGB或者BGR色彩空间到CIE LAB色彩空间或者反变换等RGB与 BGR或者HLS等的互相之间转换。
图像色彩空间的转换后续会补充说明,此处只做了解。
[6]:cvCanny函数
void cvCanny( const CvArr* image,CvArr* edges,double threshold1,double threshold2, int aperture_size=3 );
用途:用于图像的边缘检测
image:输入图像,这个必须是单通道的,即灰度图
edges:​输出的边缘图像 ,也是单通道的,但是是黑白的
threshold1:第一个阈值
​threshold2:第二个阈值
aperture_size Sobel:算子内核大小
函数 cvCanny 采用 Canny 算法发现输入图像的边缘而且在输出图像中标识这些边缘。threshold1和threshold2 当中的小阈值用来控制边缘连接,大的阈值用来控制强边缘的初始分割。
Canny算法是边缘检测算法的一种,明天我将进行一定的测试,这里先只了解!


思路整理:不知道大家看了这个代码之后有没有这个感觉,多个图像单窗口显示实际上就想Java里JFrame、JPanne、控件之间的关系,先划分一个大的区域,在利用坐标和区域大小关系来分割区域放置图片。
  • 大小: 209.3 KB
2
2
分享到:
评论

相关推荐

    OpenCV_编程简介(入门必读)

    摘要: 本文旨在帮助读者快速入门OpenCV,而无需阅读冗长的参考手册。掌握了OpenCV的以下基础知识后,有需要的话再查阅相关的参考手册。 目录  [隐藏] 1 一、简介 1.1 1、OpenCV的特点 1.1.1 (1) 总体描述 ...

    学习opencv中文版

    图书目录: 第1章 概述 什么是OpenCV OpenCV的应用领域 什么是计算机视觉 OpenCV的起源 下载和安装OpenCV 通过SVN获取最新的OpenCV代码 更多OpenCV文档 OpenCV的结构和内容 移植性 练习 第2章 OpenCV入门 ...

    学习OPENCV(中文版)

    第2章 OpenCV入门 开始准备 初试牛刀—— 显示图像 第二个程序—— 播放AVI视频 视频播放控制 一个简单的变换 一个复杂一点的变换 从摄像机读入数据 写入AVI视频文件 小结 练习 第3章 初探OpenCV OpenCV的基本数据...

    01.图像处理基础知识及OpenCV入门函数1

    1.图像基础知识 2.OpenCV读写图像 3.OpenCV像素处理 1.二值图像 2.灰度图像 3.彩色图像 1.读入图像 2.显示图像 3.窗口等待 4.删

    opencv 编程入门

    • 窗口管理 • 输入设备 • OpenCV 基础数据结构 • 图像数据结构 • 矩阵与向量 • 其他数据结构 • 图像处理 • 创建与释放图像结构空间 • 读入与存储图像 • 读取图像元素 • 图像转换 • 绘图命令 •...

    【C++】OpenCV漫水填充示例程序 by浅墨

    博文《 【OpenCV入门教程之十五】水漫金山:OpenCV漫水填充算法(Floodfill)》的配套详细注释源代码。 配套讲解程序的博文网址: http://blog.csdn.net/poem_qianmo/article/details/28261997 1.已将dll打包到...

    OPENCV 摄像窗口

    opencv 调用摄像头的程序,给opencv编程入门的童鞋。 其程序框架值得学习。附带部分动态链接库。

    firrst.zip_firrst_opencv window

    该文件是opencv的入门程序,读取图片,读完之后再在窗口上显示

    Sign-Language-Recognition-Using-Hand-Gestures-Keras-PyQT5-OpenCV:学术课程工作项目,以定制能力为手语翻译服务

    项目名称使用手势识别手语Keras PyQT5 OpenCV入门所有源代码都可在SourceCode目录中找到。 它需要python 3.6或更高版本才能与tensorflow同步。 源代码目录中可用的winGuiAuto.py包含hwnd处理程序,该处理程序用于...

    [opencv] 007 简单鼠标回调与矩形绘制

    在opencv自己创建的窗口中响应鼠标消息,并绘制鼠标走过的矩形。(本代码为up主学习毛星云《opencv3编程入门》编写)

    Opencv在C++上运行视频和图片操作

    // 入门使用技巧: // 1. 使用解决方案资源管理器窗口添加/管理文件 // 2. 使用团队资源管理器窗口连接到源代码管理 // 3. 使用输出窗口查看生成输出和其他消息 // 4. 使用错误列表窗口查看错误 // 5. 转到“项目”&gt;...

    Visual C++数字图像处理开发入门与编程实践2-8章源代码

    第七章 TestOpenCV是一个应用OpenCV提供的函数进行图片显示和保存的应用程序,注意TestOpenCV需要OpenCV提供的库支持,因此请首先到相关网站上下载并安装OpenCV 第八章 本章实例是一个类似ACDSee的图像...

    Python图像处理示例代码

    代码中包括了创建窗口、调整窗口大小、读取视频帧、显示图像、等待按键输入、保存图像等功能。通过运行这段代码,您可以学习如何使用Python和OpenCV来进行图像处理和视频播放的基本操作。这个示例代码可以作为入门...

    Visual C++数字图像处理开发入门与编程实践第10章

    第七章 TestOpenCV是一个应用OpenCV提供的函数进行图片显示和保存的应用程序,注意TestOpenCV需要OpenCV提供的库支持,因此请首先到相关网站上下载并安装OpenCV 第八章 本章实例是一个类似ACDSee的图像...

    OpenCV学习指南(四)图像滤波算法

      本文将是一篇为图像处理的初学者准备的滤波算法的入门文章。理论在前,代码在后。 算法 高斯滤波算法   一维高斯函数 G(x)=12πe−x22σ2 G(x) = \frac{1}{\sqrt{2\pi }}e^{-\frac{x^{2}}{2\sigma ^{2}}} G(x)...

    ArcCatalog中文使用手册

    第二章 快速入门教程 练习1:建立地理数据目录 8 练习2:浏览数据并将其添加到地图上 12 练习3:管理Shape文件 29 第三章 Catalog基础 37 启动ArcCatalog 38 ArcCatalog窗口 39 通过Catalog浏览 40 重新配置...

    C++ QT5跨平台界面编程从入门到实战

    001 介绍 002 QT5开发环境qtcreatorSDK和vs插件下载和安装 003 QT的SDK中各个目录和文件功能说明 004 创建第一个qtcreator项目并确定文件和目录的... 015 qmake引入qt库创建窗口设置头文件分析makefile并设置输出

    raspberry-touchtable:基于 Raspberry Pi 和 Qt5 的触控板

    覆盆子触控表 基于 Raspberry Pi 和 Qt5 的触控板 茶几由以下组成: x2 树莓派 x4 红外线投影仪 ... 它应该显示一个 1280x800 的黑色窗口(模拟可触摸的视频投影仪屏幕) 打开“DeviceAcquisitionT

    用matlab画饼状图代码-onyon:适用于C++的可扩展且灵活的数据可视化框架

    可以在窗口中显示图像,(目前需要OpenCV支持) 捕获鼠标移动和键盘按键以用于可视化。 独立于平台和C ++ 98的代码应可以使用过去二十年中完成的任何编译。 (除了将显示窗口隔离到一个类之外) 入门 一个样品。 ...

Global site tag (gtag.js) - Google Analytics