1. 加载图像(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 添加了相应的文件格式库,才可支持其格式。

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

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

3. 修改图像(cv::cvtColor)

cvtColor的功能是把图像从一个色彩空间转换到另一个色彩空间。有三个参数如下:

第一个参数表示原图像

第二个参数表示色彩空间转换之后的图像

第三个参数表示转换方式,如:CV_BGR2GRAY、CV_BGR2HSV等

代码如下:

cvtColor(src, outputImage, CV_BGR2GRAY);

4. 保存图像(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()函数不会进行 醒,将直接覆盖掉以前的文件。

5. 读视频

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;
}

6. 写视频

使用 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;
}

7. imread()RGB的转换

方法转自:知乎

我们在使用OpenCV时,经常需要将处理过的图片展示出来,由于OpenCV中显示图片的函数cv2.imshow()功能往往不能满足我们的需求,所以经常用Matplotlib显示图像,方便结果图片的放大、保存等操作。

但是,OpenCV和Matplotlib中图片的像素排列方式略有不同。OpenCV中图片像素按照BGR(HWC)方式排列,而Matpoltlib中图片按照RGB方式排序,这样使用OpenCV读入的图片经过Matplotlib展示时,就会出现反相问题。

这里使用OpenCV的logo作为实验对象:

img = cv.imread("logo.png")#使用OpenCV读入图像
plt.subplot(111);plt.imshow(img);plt.title("Original")#使用matplotliob展示图片

与原图相比,上图的红色部分与蓝色部分交换了位置,意思是图片中红色像素和蓝色像素排列位置做了交换,印证了读入的BGR格式经过Matplotlib展示后变成了RGB格式。而且绿色的部分也有明显的色差。

要想正确的显示图片,必须先把读入的BGR图片中的B通道和R通道交换位置。这里有两种可行的方法可以实现BGR 2 RGB操作。

方法1:先拆分通道B、G、R,再合并通道R、G、B。

b,g,r = cv.split(img)#拆分通道
img_1 = cv.merge([r,g,b])#合并通道

在拆分通道时,除了使用OpenCV的split()方法,还可以用Numpy的索引:

b = image[:,:,0]#得到蓝色通道
g = image[:,:,1]#得到绿色通道
r = image[:,:,2]#得到红色通道

在Matplotlib中显示:

plt.subplot(111);plt.imshow(img);plt.title("Original")
plt.subplot(122);plt.imshow(img_1);plt.title("Display_RGB")



在第二幅图片中,可以看到展示结果与原图一致。

方法2:直接使用Numpy索引

我们都知道Numpy在计算这种大型矩阵时,索引的效率很高,所以下面的方法简单高效,及其推荐使用。

img_2 = img[:,:,::-1]
plt.subplot(131);plt.imshow(img);plt.title("Original")
plt.subplot(132);plt.imshow(img_1);plt.title("Display_RGB")
plt.subplot(133);plt.imshow(img_2);plt.title("Display_RGB")
plt.show()

也可以

img = cv2.imread(fengmian)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # cv2默认为bgr顺序

8. 图像的膨胀(dilate)和腐蚀(erode)

详细说明

需要注意,腐蚀和膨胀是对白色部分(高亮部分)而言的,不是黑色部分。膨胀就是图像中的高亮部分进行膨胀,“领域扩张”,效果图拥有比原图更大的高亮区域。腐蚀就是原图中的高亮部分被腐蚀,“领域被蚕食”,效果图拥有比原图更小的高亮区域。

[OpenCV]OpenCV常用语法函数与坑点的更多相关文章

  1. OpenCV计算机视觉学习(1)——图像基本操作(图像视频读取,ROI区域截取,常用cv函数解释)

    1,计算机眼中的图像 我们打开经典的 Lena图片,看看计算机是如何看待图片的: 我们点击图中的一个小格子,发现计算机会将其分为R,G,B三种通道.每个通道分别由一堆0~256之间的数字组成,那Ope ...

  2. OpenCV中的绘图函数-OpenCV步步精深

    OpenCV 中的绘图函数 画线 首先要为画的线创造出环境,就要生成一个空的黑底图像 img=np.zeros((512,512,3), np.uint8) 这是黑色的底,我们的画布,我把窗口名叫做i ...

  3. OpenCV混合高斯模型函数注释说明

    OpenCV混合高斯模型函数注释说明 一.cvaux.h #define CV_BGFG_MOG_MAX_NGAUSSIANS 500 //高斯背景检测算法的默认参数设置 #define CV_BGF ...

  4. 【opencv基础】detectmultiscale函数详解

    前言 简单的人脸检测程序可以直接基于opencv的函数库进行实现,本文介绍一下detectMultiScale函数. 函数简介 opencv2人脸检测使用的是detectMultiScale函数,可以 ...

  5. 基础常用JS函数和语法

    100多个基础常用JS函数和语法集合大全  来源:http://www.cnblogs.com/hnyei/p/4605103.html 网站特效离不开脚本,javascript是最常用的脚本语言,我 ...

  6. 基础学习笔记之opencv(24):imwrite函数的使用

    http://www.cnblogs.com/tornadomeet/archive/2012/12/26/2834336.html 前言 OpenCV中保存图片的函数在c++版本中变成了imwrit ...

  7. 超越OpenCV速度的MorphologyEx函数实现(特别是对于二值图,速度是CV的4倍左右)。

    最近研究了一下opencv的 MorphologyEx这个函数的替代功能, 他主要的特点是支持任意形状的腐蚀膨胀,对于灰度图,速度基本和CV的一致,但是 CV没有针对二值图做特殊处理,因此,这个函数对 ...

  8. api日常总结:前端常用js函数和CSS常用技巧

    我的移动端media html{font-size:10px} @media screen and (min-width:321px) and (max-width:375px){html{font- ...

  9. oracle(sql)基础篇系列(一)——基础select语句、常用sql函数、组函数、分组函数

        花点时间整理下sql基础,温故而知新.文章的demo来自oracle自带的dept,emp,salgrade三张表.解锁scott用户,使用scott用户登录就可以看到自带的表. #使用ora ...

随机推荐

  1. TCP requires two packet transfers to set up the connection before it can send data

    wHTTP重用现存连接来减少TCP建立时延. HTTP The Definitive Guide 4.2.3 TCP Connection Handshake Delays When you set ...

  2. 剑指Offer——构建乘积数组

    题目描述: 给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]. ...

  3. 自建YUM仓库

    YUM主要用于自动安装.升级rpm软件包,它能自动查找并解决rpm包之间的依赖关系. 要成功的使用YUM工具安装更新软件或系统,就需要有一个包含各种rpm软件包的repository(软件仓库),这个 ...

  4. centos7 启动docker失败--selinux-enabled=false

    centos7,执行完安装命令: yum install docker 执行启动命令: systemctl   start docker  ,报下面错误: Error starting daemon: ...

  5. leetcode 旋转单链表

    Given a linked list, rotate the list to the right by k places, where k is non-negative. Example 1: I ...

  6. git子模块submodule

    添加submodule: git submodule add 子模块git地址  把这个module放置的文件夹(这个文件夹须事先不存在) git submodule add http://xxx.x ...

  7. error: https://packages.elastic.co/GPG-KEY-elasticsearch: import read failed(2).

    安装filebeat报错: curl: (35) SSL connect errorerror: https://packages.elastic.co/GPG-KEY-elasticsearch: ...

  8. keeplived + mysql双主复制部署 --原创

    环境: master 1: 192.168.100.10  oracle  linux 7.4  mysql 5.7.1 master 2: 192.168.100.11 oracle  linux ...

  9. C# 各种导入 Excel 文件的数据的方法总结

    在导入之前都需要将上传的文件保存到服务器,所以避免重复的写这些代码,先贴出上传文件并保存到服务器指定路径的代码. protected void btnImport_Click(object sende ...

  10. PKU 2506 Tiling(递推+高精度||string应用)

    题目大意:原题链接有2×1和2×2两种规格的地板,现要拼2×n的形状,共有多少种情况,首先要做这道题目要先对递推有一定的了解.解题思路:1.假设我们已经铺好了2×(n-1)的情形,则要铺到2×n则只能 ...