您的位置:首页 > 运维架构

【OpenCV_03】图像载入,显示和输出 Read & Display Image

2016-05-24 19:46 627 查看


图像的载入,显示和输出

这篇博客我回谈一谈,如何通过采用OpenCV的库函数将图像载入,显示以及输出。首先,打开C++的IDE编程环境新建一个工程,(必须把OpenCV的环境设置好在IDE下)

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "opencv2/highgui/highgui.hpp"
#include <iostream>

using namespace cv;
using namespace std;

int main( int argc, const char** argv )
{
Mat img = imread("MyPic.JPG", CV_LOAD_IMAGE_UNCHANGED);
//read the image data in the file "MyPic.JPG" and store it in 'img'

if (img.empty()) //check whether the image is loaded or not
{
cout << "Error : Image cannot be loaded..!!" << endl;
//system("pause"); //wait for a key press
return -1;
}

namedWindow("MyWindow", CV_WINDOW_AUTOSIZE);
//create a window with the name "MyWindow"
imshow("MyWindow", img);
//display the image which is stored in the 'img' in the "MyWindow" window

waitKey(0); //wait infinite time for a keypress

destroyWindow("MyWindow"); //destroy the window with the name, "MyWindow"

return 0;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


在运行程序之前,在C++源文件文件夹里放一个叫 (MyPic.JPG) 文件名的图片,否则就需要设置函数imread()的第一个参数为图片的绝对路径。 

代码解释
#include "stdafx.h"

因为是在 Visual Studio下开发,所以需要加上。

#include "opencv2/highgui/highgui.hpp"

imread()namedWindow()imshow() and waitKey() 的定义需要包含以上头文件。上面定义的Mat类的对象,在头文件
"opencv2/core/core.hpp"已经声明。 It is declared in "opencv2/core/core.hpp" header
file. 但是代码中为什么没有?因为在"opencv2/highgui/highgui.hpp" 头文件已经包含了,所以不需要再包含一次了。

using namespace cv;
所有的数据结构和函数都在 "opencv2/core/core.hpp" 及 "opencv2/highgui/highgui.hpp"声明在cv的命名空间里。所以在include头文件后面添加
using namespace cv;
或者每个OpenCV函数和数据前面加 'cv::'  (e.g
- cv::Mat, cv::imread() , etc)。

'#include <iostream>' 及
'using namespace std'由于在代码里用到了 'cout' 输出字符串,这是C++语法里需要熟悉的。

Mat img = imread(const string& filename, int flags=CV_LOAD_IMAGE_COLOR)
Mat 是以[b]矩阵存储图片的数据结构,[/b]在 "opencv2/core/core.hpp"头文件里声明。

imread()函数声明在"opencv2/highgui/highgui.hpp"头文件.
从文件里载入图片并且存入Mat的数据结构中。

imread() 函数的参数
filename - 图片路径,如果仅给给出名字,那么需要和C++源文件在同一个文件夹下,否则就得给出绝对路径。
flags - 有4种可能的输入
CV_LOAD_IMAGE_UNCHANGED - image-depth=8 bits per pixel in each channel,  no. of channels=unchanged 
CV_LOAD_IMAGE_GRAYSCALE - image depth=8 bits,  no. of channels=1
CV_LOAD_IMAGE_COLOR - image-depth=?,  no. of channels=3
CV_LOAD_IMAGE_ANYDEPTH - image-depth=unchanged ,  no. of channels=?
CV_LOAD_IMAGE_ANYCOLOR - image-depth=?,  no. of channels=unchanged 

也可以把上面的参数组合起来
e.g -

CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR - image-depth=unchanged,  no. of channels=unchanged 
CV_LOAD_IMAGE_COLOR | CV_LOAD_IMAGE_ANYDEPTH - image-depth=unchanged,  no. of channels=3

如果不清楚需要什么样的数据结构, 采用 CV_LOAD_IMAGE_COLOR作为函数 imread() 的第2个参数。

为了理解位深以及通道的概念,需要了解图像处理的部分知识,下面简单介绍一个图像处理。

每个数字图像都是由像素构成的,每个像素都是有一定值的。像素的最小值为0代表黑色,随着像素值增加,像素的亮度也随着增加。在计算机内存里,十进制表示的255表示白色。每个像素都有一个固定值的bits。像素的最大值可以是255,(即11111111二进制)。

位深又是什么呢?位深意思是每个像素值的比特数。如果位深为8,那么每个像素可以表示的值为0~255,如果是4,那么就是0~15 (即1111二进制)。 

举个简单的例子,位深为8比特的图,每个表格代表一个像素,那么每个像素的值为0~255。

下面是此图的参数.
 位深为 8 bit
1 channel (灰度图 )
高为4个像素 
宽为5个像素
图像分辨率为 4x5.
灰度图,如果像素值高,就会比较亮,如果像素值低,就会比较暗。



Grayscale Image with image depth of 8
下面介绍一个简单的模型是彩色图像。彩色 图像含有至少三个通道,Red, Green and Blue.任何颜色都可以由这三原色构成,所以说任何一个像素都是RGB三色的组合。 (255, 0, 0)代表红色. (0, 255, 0)代表绿色, (255, 0, 255) 为紫色,以此类推可以创建丰富多彩的颜色。由于每个像素为8
x 3 bits (每个通道为8 bits)位深为24。

下面是此图的参数.
 位深为 24 bit
3 channels 
高为4个像素 
宽为5个像素
图像分辨率为4x5.



R, G, B planes of a color image
if (img.empty())

如果 imread()函数载入图像失败,'img' 将不会载入任何数据,因此 'img.empty()' 将返回true. 检测载入图像,成功还是失败退出程序是有必要的。否则在执行imshow()函数时程序执行将崩溃。

bool Mat::empty()

This function returns true, if Mat::data==NULL or Mat::total() == 0

 //system("pause");

如果是采用 Visual Studio最好不要把这句注释掉,除非按任意键否则程序将一直暂停。如果注释掉,程序将在执行完立即退出用户看不到任何错误信息。

void namedWindow(const string& winname, int flags = WINDOW_AUTOSIZE);        // 这个函数是创建一个窗口

参数-
winname - 窗口的名称,会显示在新建窗口的标题栏
flags - 定义窗口尺寸,有两种选择
WINDOW_AUTOSIZE - 用户无法调整窗口尺寸,图像以原始分辨率显示
CV_WINDOW_NORMAL - 用户可以自由调整窗口大小

void imshow(const string& winname, InputArray mat);
这个函数是显示存储在 'mat'
里面的
图片在一个winname的窗口.如果窗口参数 为WINDOW_AUTOSIZE图像将以原始大小显示,否则可以调整。

Parameters -
winname -
窗口的名称,会显示在新建窗口的标题栏.
mat - 存储图片数据

int waitKey(int delay = 0)
waitKey()函数等待特定时间按下键,指定为延迟delay (毫秒ms). 如果 delay 为0或者负数,即无限制等待直到按下某个键。这个函数返回按下键的ASCII值使得程序继续运行。如果没有在定义时间内按下任何键,程序降返回-1后继续运行。
void destroyWindow(const string& winname)
这个函数是用来关闭打开的窗口释放相关内存空间。

总结

当运行这个程序的时候,图像 'MyPic.JPG'呗载入变量 Mat的数据类型的'img' 中, 命名为'MyWindow'的窗口被打开,'img'载入窗口。这个图像的窗口一直被展示直到某个键按下

Create a Blank Image & Display 创建一个空白图像&图像显示

这段程序和之前的非常类似,这个是创建一个空白图像,之前一个是载入已存在的图像。

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "opencv2/highgui/highgui.hpp"
#include <iostream>

using namespace cv;
using namespace std;

int main( int argc, const char** argv )
{
Mat img(500, 1000, CV_8UC3, Scalar(0,0, 100));
//create an image ( 3 channels, 8 bit image depth, 500 high, 1000 wide,
//(0, 0, 100) assigned for Blue, Green and Red plane respectively. )

if (img.empty()) //check whether the image is loaded or not
{
cout << "Error : Image cannot be loaded..!!" << endl;
//system("pause"); //wait for a key press
return -1;
}

namedWindow("MyWindow", CV_WINDOW_AUTOSIZE); //create a window with the name "MyWindow"
imshow("MyWindow", img); //display the image which is stored in the 'img' in the "MyWindow" window

waitKey(0);  //wait infinite time for a keypress

destroyWindow("MyWindow"); //destroy the window with the name, "MyWindow"

return 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////




Create & Display Image
新的OpenCV函数
 Mat::Mat(int rows, int cols, int type, const Scalar& s);

这是Mat类众多构造函数中的一个,用来初始化目标的。

参数 :
rows - 2维数组列高 ( 图像高度的像素数目)
cols - 2维数组行宽 ( 图像宽度的像素数目)
type - 指定为位深,  这里给的参数是CV_8UC3 即8 bit 无符号整数三通道,下面是可能的参数选择
CV_8UC1 -
8 bit 无符号整数单通道
CV_8UC3 -
8 bit 无符号整数三通道
CV_64FC1 -
64 bit 浮点数单通道

s -初始化由s给出的值的每个数组元素。在上面的应用程序中,我给Scalar(0,0,100)。因此,它与0,第2通道(绿色平面)与0和100。所以,我的最终图像是红色的第3路(红平面)初始化我的第一个通道(蓝色平面)。你可以试试这三种不同的组合,看到了输出图像。

本章小结

在本章里,创建了500X1000的一个3通道的图像。8 bit 无符号整数三通道(8x3
= 24 bits per each pixel)  ,每个像素赋scalar 值为 (0,0,100),意思是第1、2个通道全为0,第3个通道都为100,所以看到实验结果显示的为一张红色图像。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: