`

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 入门指南** OpenCV(开源计算机视觉库)是一个强大的计算机视觉和机器学习软件库,适用于图像处理和计算机视觉领域的各种任务。它包含了众多的预编译的函数和算法,支持多种编程语言,如C++, Python, Java...

    Opencv入门操作---导入与存储图片

    // 显示图片 cv::imshow("图片", image); cv::waitKey(0); // 等待用户按键,0表示无限等待 cv::destroyAllWindows(); // 关闭所有窗口 return 0; } ``` 在这个示例中,我们首先调用`imread()`函数读取图片,...

    OpenCV3编程入门--第三版

    然后,会从最基本的操作,如创建一个窗口显示图像开始,逐步深入到图像处理的核心概念,包括像素操作、图像滤波、形态学操作、轮廓查找、图像分割等。 随着学习的深入,读者将接触到更高级的主题,如特征检测和描述...

    OpenCV入门小例子

    本教程将引导你通过一个简单的OpenCV入门项目,理解如何在Windows环境下,利用OpenCV 2.4.9版本与Visual Studio 2010进行集成开发。 首先,我们需要安装必要的开发环境。确保你已经安装了Visual Studio 2010,并且...

    termuxpython打开摄像头-OpenCV-Python入门教程2-打开摄像头.pdf

    为了显示图像,`cv2.imshow()`函数用于创建一个窗口并在其中显示图像。`cv2.waitKey()`函数用于监听键盘输入,这里设置为1意味着每帧都会检查一次按键,若按下'q'键则退出程序。 要获取摄像头的分辨率,可以使用`...

    Intro-opencv-vadim-part-1

    《OpenCV基础教程:Vadim的入门课程第一部分》 OpenCV(开源计算机视觉库)是一个强大的跨平台计算机视觉库,它包含了用于图像处理和计算机视觉的各种算法。本教程,"Intro-opencv-vadim-part-1",是Vadim的OpenCV...

    OPENCV入门示例1

    **OpenCV 入门示例1** ...总的来说,OpenCV入门示例1是一个很好的起点,它教你如何在VS2017上设置环境并读取图像。随着对OpenCV的深入学习,你将能够实现更多复杂的功能,解决实际的计算机视觉问题。

    opencv 快速入门教程

    **OpenCV快速入门教程** OpenCV(开源计算机视觉库)是一个强大的跨平台计算机视觉库,它包含了大量的图像处理和计算机视觉算法,广泛应用于图像分析、机器学习、深度学习以及人工智能领域。本教程将引导初学者逐步...

    OpenCV教程-基础篇光盘

    本教程的基础篇光盘旨在帮助初学者快速入门OpenCV,结合配套教材,将为学习者提供一个全面而扎实的起点。 光盘内容主要包括刘晓敏老师的OpenCV基础教程源代码,这是一份宝贵的实践资源。通过这些源代码,你可以了解...

    OpenCV入门及示例源代码

    这个压缩包文件“OpenCV入门及示例源代码”显然是为初学者设计的,旨在介绍如何使用OpenCV进行图像处理,并通过实例源代码加深理解。 1. **OpenCV基本概念** - **安装与环境配置**:OpenCV可以在多种操作系统上...

    Opencv-Python教程

    - 如何使用OpenCV的窗口创建函数来显示图像和视频 - OpenCV中的事件处理机制 - 如何响应用户输入,如键盘和鼠标事件 - 创建和使用滑动条控件来动态调整图像处理参数 3. Core Operations 核心操作部分涉及对图像的...

    OpenCV轻松入门,opencv轻松入门面向pythonPDF下载,Python

    OpenCV(开源计算机视觉库)是计算机视觉领域中一个广泛使用的库,尤其在Python编程语言中,它提供了丰富的功能,让开发者能够轻松处理图像和视频数据。本篇将深入介绍OpenCV的基础知识,以及如何使用Python与OpenCV...

    OpenCV入门教程

    1. 图像读取与显示:使用`cv2.imread()`函数读取图片,`cv2.imshow()`函数显示图片,配合`cv2.waitKey()`控制窗口关闭。 2. 图像处理:包括图像的裁剪、旋转、缩放、色彩空间转换(如BGR到灰度或HSV),这些操作通过...

    Intro-opencv-vadim-part-2

    本教程“Intro-opencv-vadim-part-2”是Vadim主讲的OpenCV入门系列的第二部分,旨在帮助初学者深入理解和掌握OpenCV的基本概念和操作。 在这一部分中,我们将主要探讨以下几个关键知识点: 1. **图像加载与显示**...

    python_opencv中文教程

    本教程主要围绕《OpenCV-Python-Tutorial-中文版》和《OpenCV入门教程》两本书籍展开,旨在帮助初学者快速掌握OpenCV在Python中的应用。 ### 1. 安装OpenCV 首先,要开始使用Python和OpenCV,我们需要安装必要的库...

    opencv 入门学习官方文档

    例如,使用OpenCV加载并显示图像的代码示例会指导用户如何读取一张图片文件到内存中,并使用OpenCV提供的函数显示在窗口里。 除了基础的图像加载和显示操作,文档还涉及了更深层次的图像处理技术,比如如何通过...

    OpenCV3-初级图像混合-线性混合操作

    5. **显示结果**:最后,使用`cv2.imshow()`函数展示混合后的图像,并使用`cv2.waitKey()`等待用户按键,然后调用`cv2.destroyAllWindows()`关闭窗口。 在压缩包文件"linear_add"中,可能包含了一个示例程序,演示...

    OpenCV-Python入门教程

    OpenCV-Python入门教程 OpenCV是计算机视觉和机器学习领域中的一个非常流行的开源库,Python是目前最流行的编程语言之一。OpenCV-Python是OpenCV库的Python接口,提供了大量的计算机视觉和机器学习功能。在本教程中...

    Opencv-python中文教程

    1. 图像的读取、显示和保存:OpenCV提供了cv2.imread()函数用于读取图片,cv2.imshow()函数用于显示图片,以及cv2.imwrite()函数用于保存图片。cv2.imread()可以根据指定的标志读取彩色图像或灰度图像。cv2.imshow()...

    Opencv3编程入门

    本入门指南旨在帮助初学者整理一些常用的OpenCV函数,按照功能分类,使其便于学习和使用。 ### 1. IplImage和基本图像操作 OpenCV使用IplImage结构体来表示图像。它包含图像头信息,如图像的高度、宽度、颜色通道...

Global site tag (gtag.js) - Google Analytics