OpenCV学习之路(一)——加载、显示、修改、保存图像

加载图像(cv::imread)

imread()功能是加载图像文件成为一个Mat对象,如果读取文件失败,则会返回一个空矩阵,即 Mat::data 的值是 NULL。imread()函数的声明如下:

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

其中第一个参数是表示图像文件名称;第二个参数表示加载的图像是什么类型,支持常见的三个参数值:

  • IMREAD_UNCHANGED(<0)表示加载原图,不做任何改变
  • IMREAD_GRAYSCALE(0)表示把原图作为灰度图像加载进来
  • IMREAD_COLOR(>0)表示把原图作为RGB图像加载进来

imread()函数支持多种文件格式,且该函数是根据图像文件的内容来确定文件格式,而不是根据文件的扩展名来确定。所只是的文件格式如下:

  • Windows 位图文件 - BMP, DIB;
  • JPEG 文件 - JPEG, JPG, JPE;
  • 便携式网络图片 - PNG;
  • 便携式图像格式 - PBM,PGM,PPM;
  • Sun rasters - SR,RAS;
  • TIFF 文件 - TIFF,TIF;
  • OpenEXR HDR 图片 - EXR;
  • JPEG 2000 图片- jp2。

你所安装的 OpenCV 并不一定能支持上述所有格式,文件格式的支持需要特定的库,只有在编译 OpenCV 添加了相应的文件格式库,才可支持其格式。

显示图像(cv::nameWindows与cv::imshow)

  • namewindows功能是创建一个OpenCV窗口,它是由OpenCV自动创建与释放,你无须手动销毁它。
  • 常见用法 nameWindows("windowTitle", WINDOW_AUTOSIZE)
  • WINDOW_AUTOSIZE 会自动根据图像大小,显示窗口大小,不能认为改变窗口大小
  • WINDOW_NORMAL 跟QT集成的时候会使用,允许修改窗口大小
  • imshow 根据窗口名称显示图像到窗口上去,第一个参数是窗口名称,第二个参数是Mat对象

修改图像(cv::cvtColor)

cvtColor的功能是把图像从一个色彩空间转换到另一个色彩空间。有三个参数如下:
第一个参数表示原图像
第二个参数表示色彩空间转换之后的图像
第三个参数表示转换方式,如:CV_BGR2GRAY、CV_BGR2HSV等
代码如下:

cvtColor(src, outputImage, CV_BGR2GRAY);

保存图像(cv::imwrite)

将图像写入文件,可使用 imwrite()函数,该函数的声明如下:

bool imwrite( const string& filename, InputArray img, const vector<int>& params=vector<int>());

文件的格式由 filename 参数指定的文件扩展名确定。推荐使用 PNG 文件格式。BMP 格式是无损格式,但是一般不进行压缩,文件尺寸非常大;JPEG 格式的文件娇小,但是 JPEG 是有损压缩,会丢失一些信息。PNG 是无损压缩格式,推荐使用。
imwrite()函数的第三个参数 params 可以指定文件格式的一些细节信息。这个参数里面的数值是跟文件格式相关的:

  • JPEG:表示图像的质量,取值范围从 0 到 100。数值越大表示图像质量越高,当然文件也越大。默认值是 95。
  • PNG:表示压缩级别,取值范围是从 0 到 9。数值越大表示文件越小,但是压缩花费的时间也越长。默认值是 3。
  • PPM,PGM 或 PBM:表示文件是以二进制还是纯文本方式存储,取值为0 或 1。如果取值为 1,则表示以二进制方式存储。默认值是 1。

并不是所有的 Mat 对象都可以存为图像文件,目前支持的格式只有 8U 类型的单通道和 3 通道(颜色顺序为 BGR)矩阵;如果需要要保存 16U 格式图像,只能使用 PNG、JPEG 2000 和 TIFF 格式。如果希望将其他格式的矩阵保存为图像文件,可以先用 Mat::convertTo()函数或者 cvtColor()函数将矩阵转为可以保存的格式。
注意:在保存文件时,如果文件已经存在,imwrite()函数不会进行 醒,将直接覆盖掉以前的文件。

读视频

VideoCapture 既可以从视频文件读取图像,也可以从摄像头读取图像。可以使用该类的构造函数打开视频文件或者摄像头。如果 VideoCapture 对象已经创建,也可以使用 VideoCapture::open()打开,VideoCapture::open()函数会自动调用VideoCapture::release()函数,先释放已经打开的视频,然后再打开新视频。

VideoCapture cap(0);  //打开第一个摄像头
VideoCapture cap("filename.avi");  //打开视频文件

如果要读一帧,可以使用 VideoCapture::read()函数。VideoCapture 类重载了>>操作符,实现了读视频帧的功能。

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main(int argc, char** argv)
{
    VideoCapture cap(0);    //打开第一个摄像头
    if(!cap.isOpened()) {   //检查是否成功打开
        cerr << "Can not open a camera or file." << endl;
        return -1;
    }
    Mat edges;
    namedWindow("edges",1); //创建窗口
    while(1) {
        Mat frame;
        cap >> frame;  //从 cap 中读一帧,存到 frame
        if(frame.empty()){  //如果未读到图像
            break;
        }
        cvtColor(frame, edges, CV_BGR2GRAY);  //将读到的图像转为灰度图
        Canny(edges, edges, 50, 150, 3);  //进行边缘 取操作
        imshow("edges", edges);     //显示结果
        if(waitKey(30) >= 0) {   //等待 30 秒,如果按键则推出循环
            break;
        }
    }
    //退出时会自动释放 cap 中占用资源
    return 0;
}

写视频

使用 OpenCV 创建视频也非常简单,与读视频不同的是,你需要在创建视频时设置一系列参数,包括:文件名,编解码器,帧率,宽度和高度等。编解码器使用四个字符表示,可以是 CV_FOURCC('M','J','P','G')、CV_FOURCC('X','V','I','D')及CV_FOURCC('D','I','V','X')等。如果使用某种编解码器无法创建视频文件,请尝试其他的编解码器。
将图像写入视频可以使用 VideoWriter::write()函数,VideoWriter 类中也重载了<<操作符,使用起来非常方便。另外需要注意:待写入的图像尺寸必须与创建视频时指定的尺寸一致。

#include <stdio.h>
#include <iostream>
#include "opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main(int argc, char** argv) {
    //定义视频的宽度和高度
    Size s(320, 240);
    //创建 writer,并指定 FOURCC 及 FPS 等参数
    VideoWriter writer = VideoWriter("/Users/Longxia/Downloads/myvideo.avi", CV_FOURCC('M','J','P','G'), 25, s);
    //检查是否成功创建
    if(!writer.isOpened()) {
        cerr << "Can not create video file.\n" << endl;
        return -1;
    }
    //视频帧
    Mat frame(s, CV_8UC3);
    for(int i = 0; i < 100; i++)
    {
        //将图像置为黑色
        frame = Scalar::all(0);
        //将整数 i 转为 i 字符串类型
        char text[128];
        snprintf(text, sizeof(text), "%d", i);
        //将数字绘到画面上
        putText(frame, text, Point(s.width/3, s.height/3),
                FONT_HERSHEY_SCRIPT_SIMPLEX, 3, Scalar(0,0,255), 3, 8);
        //将图像写入视频
        writer << frame;
    }
    //退出程序时会自动关闭视频文件
    return 0;
}```
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容