zoukankan      html  css  js  c++  java
  • opencv读取和显示图片

    转自:https://blog.csdn.net/l494926429/article/details/53031927

    一、从文件读取图像并显示

    1. 程序

    基于VS2013搭建OpenCV开发环境这篇文章的最后给出了一个简单的Demo,这个例子跟本篇使用的例子是一样的。打开C++ IDE并创建一个新的项目,新建一个源文件,粘贴下面的代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    #include <opencv2highguihighgui.hpp>
    #include <iostream>
     
    using namespace cv;
    using namespace std;
     
    int main(int argc, const char** argv)
    {
        Mat img = imread("earth.jpg", CV_LOAD_IMAGE_UNCHANGED);
        if (img.empty())
        {
            cout << "图像加载失败!" << endl;
            //system("pause");
            return -1;
        }
        //创建一个名字为MyWindow的窗口
        namedWindow("MyWindow", CV_WINDOW_AUTOSIZE);
        //在MyWindow的窗中中显示存储在img中的图片
        imshow("MyWindow", img);
        //等待直到有键按下
        waitKey(0);
        //销毁MyWindow的窗口
        destroyWindow("MyWindow");
        return 0;
    }

    在运行程序之前,将图片文件(earth.jpg)放到C++文件所在的目录。运行程序,如下图所示:

    20140326201318

    2. 解释

    下面我来解释一下这个程序。

    1
    #include <opencv2highguihighgui.hpp>

    imread(), namedWindow(), imshow() 和 waitKey() 函数都声明在这个头文件中,所以笔记得包含它。

    上面的程序中还是用了Mat数据结构,它在”opencv2/core/core.hpp”中声明的,那为什么没有包含它呢?这是因为在”opencv2/highgui/highgui.hpp”头文件中已经包含了core.hpp头文件,所以不用在我们的程序再次包含了。

    1
    using namespace cv;

    “opencv2/core/core.hpp” 和 “opencv2/highgui/highgui.hpp中所有的数据结构和函数都声明在cv命名空间,所以,必须在我们程序的头部使用它,否则就要在每个OpenCV的函数和数据结构前面都要加上”cv::”(例如:cv::Mat,cv::imread()等等)。

    1
    Mat img = imread("earth.jpg", CV_LOAD_IMAGE_UNCHANGED);

    Mat是在矩阵中存储图片的数据结构,它声明在 “opencv2/core/core.hpp”头文件中。
    imread()是声明在 “opencv2/highgui/highgui.hpp”的函数,它从文件加载一个图片并存储在Mat数据结构中。

    imread()函数的声明如下:

    1
    CV_EXPORTS_W Mat imread( const string& filename, int flags=1 );

    它的参数:

      • filename —— 文件的位置。如果只提供文件名,那么文件应该和C++文件在同一目录,否则必须提供图片的全路径。
      • flags —— 有5个可能的输入。
        • CV_LOAD_IMAGE_UNCHANGED – 在每个通道中,每个像素的位深为8 bit,通道数(颜色)保持不变。
        • CV_LOAD_IMAGE_GRAYSCALE – 位深=8 bit 通道数=1(颜色变灰)
        • CV_LOAD_IMAGE_COLOR -位深=?, 通道数=3
        • CV_LOAD_IMAGE_ANYDEPTH – 位深不变 ,通道数=?
        • CV_LOAD_IMAGE_ANYCOLOR – 位深=?, 通道数不变

        上面的值还可以组合使用,比如:
        CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR – 位深不变,通道数比便
        CV_LOAD_IMAGE_COLOR | CV_LOAD_IMAGE_ANYDEPTH – 位深不变,通道数=3

    如果你不确定使用哪个,就是用CV_LOAD_IMAGE_COLOR 。

    要理解位深和通道的概念,应该熟悉图像处理的理论知识,所以下面讨论一点这方面的内容。

    所有的数字图像都是由像素组成的,所有的像素都有值。一个像素的最小值为0,表示黑色。像素的值变大,它的亮度也会增强。每个像素分配的比特的固定数值是255(十进制),也就是说每个像素分配8个bit。所以一个像素的最大值为255(二进制为11111111)。

    那么什么是位深呢?位深就是为每个像素分配的比特。如果比特是8,每个像素的值可以是0-255。如果是4,每个像素的值可是0-15(二进制中为1111)。

    下面是一个8 bit位深的图片的简单模型。每个小矩形表示一个像素。所以每个矩形包含一个0-255的值。

    GrayscaleImage

    这张图像的一些属性:

    • 8 bit位深
    • 一个通道(所以这是一个灰度图像)
    • 高为4px
    • 宽为5px
    • 分辨率为4×5

    这是一个灰度图像(黑白图像),因为该图像没有颜色内容。像素的值越高,图像就会越亮。像素值越低,图像就会越暗。

    下面是一个彩色图像的简单模型。彩色图像至少包含3个平面:Red,Green和Blue。使用这3种颜色的特定组合可以创建任何颜色。所有的像素都是这3种颜色值的组合。(255,0,0)表示pure red。(0,255,0)表示pure green。(255,0,255)表示pure violate。它的位深为24,因为每个像素为8×3 bit (每个通道8 bit)。

    ColorImage

    这张图像的一些属性:

    • 位深24 bit
    • 3个通道(所以是彩色图像)
    • 高4px
    • 宽5px
    • 分辨率为4×5

    上面的模型,左上角的像素是(23,231,46)。它会显示为呈绿色的颜色,因为green值(231)比red(23)和blue(46)都大。

    1
    if (img.empty())

    如果imread()函数加载图像失败,’img’不会加载任何数据,因此,img.empty()应该返回true。检查是否成功加载,如果没有则退出程序是一个好的做法,否则当调用imshow()函数时,程序就会崩溃。

    1
    bool Mat::empty()

    如果Mat::data==NULL或Mat::total()==0,这个函数返回true。

    1
    system("pause");

    如果使用Visual Studio,这行注释的注释最好取消,因为它会暂停程序,知道用户按下任意键。如果不取消注释,程序会立即退出,用户也就不会看到错误信息了。

    1
    void namedWindow(const string& winname, int flags = WINDOW_AUTOSIZE);

    这个函数创建一个窗口。它的参数如下:

    • winname——窗口的名字。这个名字会显示在窗口的标题栏上。
    • flags——决定窗口的尺寸。有如下选项:
      • WINDOW_AUTOSIZE – 用户不能改变图像的尺寸,图像显示为它的原有尺寸
      • CV_WINDOW_NORMAL – 调整窗口图像的尺寸可以改变
    1
    void imshow(const string& winname, InputArray mat);

    这个函数在指定名字的窗口中显示存储在mat中的图像。如果窗口使用WINDOW_AUTOSIZE创建的,图像会显示为它的原始尺寸,否则图像会调整到窗口的尺寸大小。

    它的参数:

    • winname -窗口的名字。这个名字是namedWindow()函数创建窗口时使用的
    • mat – 存储图像数据的Mat对象
    1
    int waitKey(int delay = 0)

    waitKey()函数通过指定delay(毫秒)等待按键的时间。如果delay是0或负数,它会永久等待。如果任意键被按下,这个函数就会返回按下键的ASCII值,程序继续执行。如果指定的时间没有按下键,它返回-1,程序继续执行。

    1
    void destroyWindow(const string& winname)

    这个函数关闭名字为winname的打开的窗口并释放关联的内存。这个函数对这个程序来说不是必须的,因为当程序退出,操作系统通常会关闭所有打开的窗口并释放关联的内存。

    3. 总结

    当运行程序,图像”earth.jpg”被加载到Mat类型的变量”img”。然后一个名字为”MyWindow”的窗口打开,接着”img”被加载到窗口中。窗口和图像一起显示,直到按下任意键。

    二、创建一个空图像并显示

    这个程序和前一个非常像,唯一的不同就是这个程序创建了一个空图像,而不是从文件中加载已存在的图像。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    #include <opencv2highguihighgui.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)); //创建一个图像 ( 3个通道, 8 bit位深, 高500, 宽1000, (0, 0, 100) 分别分配给 Blue, Green and Red. )
     
        if (img.empty())
        {
            cout << "图像不能加载!" << endl;
            //system("pause");
            return -1;
        }
     
        namedWindow("MyWindow", CV_WINDOW_AUTOSIZE);
        imshow("MyWindow", img);
     
        waitKey(0);
     
        destroyWindow("MyWindow");
     
        return 0;
    }

    运行结果如下图:

    20140326235345

    OpenCV的新函数

    1
    Mat::Mat(int rows, int cols, int type, const Scalar& s);

    这是Mat的一个构造函数。它使用Scalar对象给定的值初始化Mat对象。

    它的参数:

    • rows – 2维矩阵的行数 (图像的高度像素)
    • cols – 2维矩阵的列数 ( 图像的宽度像素)
    • type – 指定图像的位深,数据类型和通道数。我提供 CV_8UC3 ,指定3个通道的8 bit无符号整数,下面是这个参数一些可能的输入值:
      • CV_8UC1 – 单通道8 bit无符号整数
      • CV_8UC3 – 3通道8 bit为无符号整数
      • CV_64FC1 – 单通道64 bit 浮点数
        如果想详细了解这方面的内容,请参见OpenCV数据结构之Mat一文的“阵列的数据类型”部分。
      • s – 使用s给定的值初始化矩阵的每个元素。在上面的程序中,给定Scalar(0,0,100),因此,它使用0初始化第一个通道(Blue),0初始化第二个通道(Green),100初始化第三个通道(Red)。所以,最终的图像是red。

    总结

    在这个程序中,我创建了一个高500,宽1000,有3个通道的图像。每个通道的每个像素分配8 bit的无符号整数(每个像素 8×3=24 bit),每个像素使用(0,0,100)指定值。这意味着,第一个通道总是0,第二个通道也总是0,第三个通道总是100,因此,最终看到的是一个red的图像。

  • 相关阅读:
    Mysql 视图笔记2
    mysql 触发器
    Mysql 视图笔记
    最详细的Log4j使用教程
    java制作简单的坦克大战
    Java数据库连接池的几种配置方法(以MySQL数据库为例)
    几种破解MySQL root密码的几种方法:
    Django URL的命令空间
    python调用jar包类
    (http://fonts.googleapis.com/css?)打开很慢解决方案
  • 原文地址:https://www.cnblogs.com/ymd12103410/p/10871171.html
Copyright © 2011-2022 走看看