1 概述 - OpenCV介绍与环境搭建

HighGUI部分

Image Process

2D Feature

Camera Calibration and 3D reconstruction

Video Analysis

Object Detection

Machine Learning

GPU加速

2 加载、修改、保存图像

1 加载图像(用cv::imread)

2 修改图像(cv::cvtColor)

3 保存图像(cv::imwrite)

4 代码演示

(1)加载图像(用cv::imread)

imread功能是加载图像文件称为一个Mat对象(类对象)(源码中Mat类有多个重载的构造函数[参数表不同])

cv::Mat cv::imread(const cv::String &filename, int flags = 1)

其中第一个参数表示图像文件名称(文件的绝对地址)

第二个参数,表示加载的图像是什么类型,常见的有三个参数值(都是enum枚举类型)

IMREAD_UNCHANGED(<0)表示加载原图,不做任何改变

IMREAD_GRAYSCALE(0)表示把原图作为灰度图像加载进来

IMREAD_COLOR(>0)表示把原图作为RGB图像加载进来

注意:OpenCV支持JPG、PNG、TIFF等常见格式图像文件加载。

(2)显示图像(cv::namedWindow与cv::imshow)

namedWindow功能是创建一个OpenCV窗口,它是由OpenCV自动创建与释放的无需自己销毁(早年需要destroyWindow)

常见用法namedWindow("Window Title", WINDOW_AUTOSIZE)

WINDOW_AUTOSIZE会自动根据图像大小,显示窗口大小,不能人为改变窗口大小

WINDOW_NORMAL,跟QT集成的时候会使用,允许修改窗口大小

imshow根据窗口名称显示图像到指定的窗口上去,第一个参数是窗口名称,第二个参数是Mat对象

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

cvtColor的功能是把图像从一个色彩空间转换到另一个色彩空间。调整亮度/饱和度时先转换空间,改变效果后,再转换回来。有三个参数

表示源图像

表示色彩空间转换之后的图像

表示源和目标色彩空间

COLOR_BGR2HLS(L->Light[亮度],S->saturation[饱和度])

COLOR_BGR2GRAY(BGR=>RGB,原因是B通道在前)

COLOR_BGR2HSV(S->saturation[饱和度])

cvtColor(image, gray_image, COLOR_BGR2GRAY)

(image, gray_image都是Mat类对象)

(4)保存图像(cv::imwrite)

保存图像到指定目标路径(?路径中一定要加文件名.后缀名)

只有8位、16位的PNG、JPG、Tiff文件格式而且是单通道或者三通到的BGR图像才可以通过这种方式保存

保存PNG格式的时候可以保存透明通道的图片

可以指定压缩参数

3 矩阵的掩膜操作

1 获取图像像素指针

2 掩膜操作解释

3 代码演示

(1)获取图像像素指针

CV_Assert(myImage.depth() == CV_8U);测试位图深度是否为8位,如果False则停止运行

位图深度:在灰度图像中8位代表从黑(0)到白(1)分为256个颜色深度;在RGB图像中代表每个通道(每个原色)都分为256个子色,总体上为256 * 256 * 256种颜色

Mat.ptr(int i = 0)(uchar是unsigned char,一个字节0~ 255,像素值也是在0~255)获取像素矩阵的指针,索引i表示第几行,从0开始计行数

获得当前行指针const uchar* current = myImage.ptr(row);

获取当前像素点P(row, col)的像素值p(row, col) = current[col];

(2)像素范围处理saturate_cast

saturate_cast(-100),返回0

saturate_cast(288),返回255

saturate_cast(124),返回124

这个函数的功能是确保RGB值的范围在0~255之间

(3)掩膜操作解释

代码示例:(RGB图像可以理解为一个像素占三个字节(R/G/B))

这是一张3*3的(255, 0, 0)的纯红色图片

(.ptr(int)是Mat类的成员函数,uchar用于表示像素0~255)

//示例中使用

Mat resultImage;

myImage.copyTo(resultImage);//将图片clone

//视频中

Mat resultImage;

resultImage = Mat::zeros(myImage.size(), myImage.type());

//clone了新对象,zeros产生一个纯黑的图像,拷贝图像大小和类型

(4)函数调用filter2D功能

定义掩膜:

Mat kernel = (Mat_(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);

Mat_是一个类模版,是对Mat的封装没有添加更多的属性。char是typename,Mat_(int _rows, int _cols)是它的一个构造函数。目的是避免多处声明数据类型导致出错

filter2D(src, dst, src.depth(), kernel);

其中src与dst是Mat类型变量、src.depth表示位图深度,有32、24、8等。

4 Mat对象

1 Mat对象与IplImage对象

2 Mat对象使用

3 Mat定义数组

(1)Mat对象与IplImage对象

Mat对象OpenCV2.0之后引进的图像数据结构、自动分配内存、不存在内存泄漏的问题,是面向对象的数据结构。分头部与数据部分

IplImage

是从2001年OpenCV发布之后就一直存在,是C语言风格的数据结构,需要开发者自己分配与管理内存,对大的程序使用它容易导致内存泄漏问题?‍

(2)Mat对象构造函数与常用方法

对象构造函数

Mat()

Mat(int rows, int cols, int type) 传入长宽像素大小,和矩阵单位类型

解释一下type矩阵类型

可以通过原对象.convertTo(目标Mat对象, 目标类型)来改变

CV_8UC1(灰度)、CV_8UC2、CV_8UC3(彩色BGR)、CV_8UC4(带透明色的BGR)都是Unsigned 8bits

CV_32FC1、CV_32FC2、CV_32FC3是float32位

CV_64FC1、CV_64FC2、CV_64FC3是double64位

Mat(Size size, int type) 传入另一个Mat对象的.size()

Mat(int rows, int cols, int type, const Scalar &s) 传入长宽,类型和Scalar像素值(Scalar(B, G, R))

Mat M(24, 24, CV_8UC3, Scalar(0, 0, 255))

其中前两个参数分别为行(row)和列(column),第三个CV_8UC3中 8表示每个通道占8位、U表示无符号、C表示Char类型、3表示通道数目是3,第四个参数是向量表示初始化每个像素值是多少,向量长度对应通道数目一致

Mat(Size size, int type, const Scalar &s)

Mat(int ndims, const int *sizes, int type)

Mat(int ndims, const int *sizes, int type, const Scalar &s)

(3)常用方法

void copyTo(Mat dst) 拷贝Mat对象。用法(拷贝到):Mat对象名.copyTo(Mat对象名);

void convertTo(Mat dst, int type) 转换Mat矩阵类型

Mat clone() 完全克隆。用法:Mat对象名 = Mat对象名.clone();

int channels() 返回通道数

int depth() 返回位图深度

bool empty() 返回是否为空对象

uchar* ptr(i=0) 返回一个指向行的指针。说明:default=0是第一行的索引

Mat::zeros(int rows, int cols, int type) 返回一个Mat对象,像素值都为0

Mat::eye(int rows, int cols, int type) 返回一个Mat对象,主对角线上像素值都为1,其他像素为0

Mat dst = Scalar( , , )括号内填入像素值,生成一个确定BGR像素的图片。若范围在0~255,则代表位图深度为8,RGB每个原色都分成255个子色。

(4)Mat对象使用

部分复制:一般情况下只会复制Mat对象的头和指针部分,不会复制数据部分

Mat A = imread(imgFilePath);

Mat B(A);

完全复制:如果想把Mat对象的头部和数据部分一起复制,可以通过如下两个API实现

Mat B = A.clone()

Mat G; A.copyTo(G);

Mat定义数组:Mat kernel = (Mat_(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);

5 图像操作

1 读写图像

2 读写像素

3 修改像素值

(1)读写像素

读一个GRAY像素点的像素值(CV_8UC1)

int intensity = img.at(row, col);

int intensity = img.at(Point(row, col));

读一个RGB像素点的像素值(CV_8UC3)

Vec3f intensity = img.at(row, col); Vec3b -> 返回值是unsigned char

int blue = intensity.val[0];

int blue = img.at(row, col)[0]; 这种写法也是对的 blue

int green = intensity.val[1]; green

int red = intensity.val[2]; red

.ptr(row)[col]和.at(row, col)[channel]的区别:

.ptr(row)[col]是在一个已展开的图像上提取像素指针,对于多通道而言(BGR三通道ptr获取像素指针时,每个位置三个通道是排开的,可以理解为一个像素位置由三个字节构成)

它的返回值类型为const _Tp * ptr<_tp n>(const cv::Vec &idx) const

.at(row, col)[channel]是在原图像位置上取出像素指针,通过[channel]获取不同通道下的像素指针的

它的返回值类型为const _Tp &at<_tp>(cv::Point pt) const

对各通道取反操作API

bitwise_not(input_img, output_img);

编译器快捷键

选中代码后Alt + 方向键 移动代码块

6 图像混合

1 理论-线性混合操作

2 相关API(addWeighted)

3 代码演示

(1)理论-线性混合操作

其中 α的取值范围为0~1之间。

(2)相关API(addWeighted)

void cv::addWeighted ( InputArraysrc1,

doublealpha,

InputArray src2,

doublebeta,

doublegamma,

OutputArray dst,

int dtype = -1

)

参数1:输入图像Mat-src1

参数2:输入图像src1的α\alphaα值

参数3:输入图像Mat-src2

参数4:输入图像src2的α\alphaα值

参数5:γ\gammaγ(gamma)值

参数6:输出混合图像

注意点: 两张图像的大小和类型必须一致才可以。

四个函数:

void add(cv::InputArray src1, cv::InputArray src2, cv::OutputArray dst, cv::InputArray mask = noArray(), int dtype = -1) 像素直接相加函数

void multiply(cv::InputArray src1, cv::InputArray src2, cv::OutputArray dst, double scale = (1.0), int dtype = -1) 像素直接相乘函数

int64 cv::getTickCount() 用于返回从操作系统启动到当前所经的计时周期数

int64=>long long是64位整数,类似的有int16=>short,int32=>int

double cv::getTickFrequency() 用于返回CPU的频率(1s内的计时周期数)

用来计算当前程序的运行时间

7 调整图像亮度与对比度

1 理论

2 代码演示

(1)理论

图像变换:

像素变换 — 点操作

邻域操作 — 区域

调整图像亮度和对比度属于像素变换。 g(i,j)=αf(i,j)+β(g(i,j)(其中α>0,β 是增益变量 )α控制对比度,β控制亮度。

小知识点:int64 类型是 long long,size_t 类型是 unsigned long long

8 绘制形状与文字

1 使用cv::Point与cv::Scalar

2 绘制线、矩形、圆、椭圆等几本几何形状

3 随机生成与绘制文本

4 代码演示

(1)使用cv::Point与cv::Scalar

Point表示2D平面上一个点(x, y)

Scalar表示至多四个元素的向量

Point和Scalar都是类模板

//Scalar源码types.hpp

typedef Scalar_ Scalar;

//Scalar_源码

template class Scalar_ : public Vec<_tp>

//Vec源码

template class Vec : public Matx<_tp cn>

//Matx源码

template class Matx

关于OpenCV中矩阵Matx和退化的单行矩阵Vec源码分析可以参考Ph.D, HUST.的OpenCV源码阅读之matx.h

(2)绘制线、矩形、圆、椭圆等几本几何形状

提醒: 当线宽设置为-1时,会填充整个形状

画线 cv::line (线的类型:LINE_4\LINE_8\LINE_AA(反锯齿))

void Draw_Line(int line_width, Mat& tmp)

{

line(tmp, Point(100, 100), Point(200, 200), Scalar(0, 0, 255), line_width, LINE_8);

}

画椭圆 cv::ellipse

void ellipse(InputOutputArray img, Point center, Size axes, double angle, double startAngle, double endAngle, const Scalar& color, int thickness = 1, int lineType =8, int shift = 0)

Point 圆心坐标

Size 椭圆长轴、短轴长度

angle 初始旋转角度

startAngle 椭圆起始角度

endAngle 椭圆终止角度(这两个用于画椭圆弧)

void ellipse(int line_width, Mat& tmp)

{

ellipse(tmp, Point(tmp.rows / 2, tmp.cols / 2), Size(tmp.rows / 4, tmp.cols / 8), 45, 0, 360, Scalar(150, 150, 0), line_width, LINE_8);

}

画矩形 cv::rectangle

Rect用来创建一个矩形对象。构造函数:

Rect::Rect()默认构造函数,矩形左上角的横纵坐标,矩形大小均为0

Rect::Rect(point&, size&)用Point对象初始化矩形左上角的横纵坐标;用**Size(width, height)**初始化矩形大小

Rect::Rect(INT, INT, INT, INT)用四个证书初始化角点的横纵坐标、矩形大小

Rect rect = Rect(100, 100, 200, 200);

//Rect rect(Point(100, 100), Size(200, 200));

void rectangle(int line_width, Mat& tmp)

{

rectangle(tmp, rect, Scalar(0, 255, 0), line_width, LINE_8);

}

画圆 cv::circle

//和椭圆很相似,Size->radius半径

void circle(int line_width, Mat& tmp)

{

circle(tmp, Point(tmp.rows / 2, tmp.cols / 2), 50, Scalar(0, 125, 125), line_width, LINE_8);

}

画填充 cv::fillPoly

void fillPoly(InputOutputArray img, const Point **pts, const int *npts, int ncontours, const Scalar &color, int lineType = 8)

Point ** pts 用来接指向Point数组的指针

int *npts 用来接一共有几个指向顶点位置的指针,实际顶点个数+1(最后一个指回初始点)

int ncontours 是几个闭环,是point[1][6]中第一维的数值

void Polygon(Mat& tmp)

{

//定义一个五边形的五个顶点,必须用数组

const Point point[1][6];

point[0][0] = Point(0, 0);

point[0][1] = Point(100, 100);

point[0][2] = Point(100, 50);

point[0][3] = Point(80, 30);

point[0][4] = Point(50, 10);

point[0][5] = Point(0, 0);

const Point* pts[] = { point[0] };

int npts[] = { 6 };//定义成数组的原因是数组名是首地址,可以直接传给指针

fillPoly(tmp, pts, npts, 1, Scalar(100, 0, 0), 8);

}

文字 putText

void putText(InputOutputArray img, const String& text, Point org, int fontFace, double frontScale, Scalar color, int thickness, int lineType)

fontFace代表字体格式,如:CV_FONT_HERSHEY_COMPLAX CV_FONT_BLACK

putTest(img, "content", Point(img.rows / 2, img.cols / 2), CV_FONT_HERSHEY_COMPLAX, 1.0, Scalar(12, 24, 200), 3, 8);

这里再次提一下waitKey函数

waitKey函数是一个等待键盘事件的函数,参数值delay<=0时等待时间无限长,delay为正整数n时至少等待n毫秒的时间才结束。在等待的期间按下任意按键时函数结束,返回按键的键值(ascii码),等待时间结束仍未按下按键则返回-1。该函数用在处理HighGUI窗口程序,最常见的便是与显示图像窗口imshow函数搭配使用

if (waitKey(delay_time) >= 0)

break;

(3)随机数生成cv::RNG

RNG rng

生成高斯随机数 rng.gaussian(double sigma)

生成正态分布随机数 rng.uniform(int a, int b) a和b是取值范围

随机生成line&“OpenCV”

void randomgenerator()

{

Size size(500, 500);

Mat src = Mat::zeros(size, IMREAD_REDUCED_GRAYSCALE_2);

RNG rng(1024);

Point p1, p2;

for (i = 0; i < 100000; i++)

{

p1 = Point(rng.uniform(0, src.cols), rng.uniform(0, src.rows));

p2 = Point(rng.uniform(0, src.cols), rng.uniform(0, src.rows));

p3 = Point(rng.uniform(0, src.cols), rng.uniform(0, src.rows));

Scalar color(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));

line(src, p1, p2, color, rng.uniform(0.5, 3), 8);

putText(src, "OpenCV", p3, rng.uniform(0, 7), rng.uniform(0.7, 2.3), color, rng.uniform(2, 3));

imshow("demo", src);

if (waitKey(30) > 0)

break;

}

}

9 模糊图像

1 模糊原理

2 中值滤波

3 双边滤波

(1)模糊原理

Smooth/Blur是图像处理中最简单和常用的操作之一

使用该操作的原因之一就为了给图像预处理时降低噪声

使用Smooth/Blur操作其背后是数学的卷积计算

通常这些卷积算子计算都是线性操作,所以又叫线性滤波

归一化盒子滤波(均值滤波)

API:

blur(Mat src, Mat dst, Size(xradius, yradius), Point(-1, -1));

注释: Point(-1, -1)意思是将输出值赋给中心点。

高斯滤波

kernel的值分布是二维的高斯分布函数(保留原有的特征)

API:

GaussianBlur(Mat src, Mat dst, Size ksize, double sigmaX, double sigmaY = 0, int borderType = BORDER_DEFAULT);

其中sigmax和sigmay必须是正数而且是奇数。

中值滤波:清除椒盐噪声

统计排序滤波器

中值对椒盐噪声有很好的抑制作用

即取该卷积核内所有值的中位数赋给中心像素

API:

medianBlur(Mat src, Mat dst, int ksize);

双边滤波:保持轮廓

可以这样理解,在高斯滤波的基础上,添加了一种类似阈值的概念,按传统的高斯滤波处理,但相邻像素值超出阈值时不做处理,保留了边缘信息。

双边滤波分为空间临近度计算的权值和像素值相似度计算的权值,在边缘附近(高频信号),离的较远的像素不会太多影响到边缘上的像素,这样就能对边缘附近的像素值予以保存。

f′是输出图像,f是输入图像,Ω是以像素点 x为中心的邻域窗口,w为滤波核。

滤波核w由与欧式距离相关的空域核ϕ以及和临近像素值差异相关的值域核ψ的点积构成。

两个核都按照高斯分布的形式

从公式可以看出当相邻像素值 f(y)和 f(x)差值越大时,越小,ψ的权重越小,这时就成空域核占主要权重,实际上就是普通的高斯滤波形式。

API:

bilateralFilter(Mat src, Mat dst, int d, double sigmaColor, double sigmaSpace, int borderType = BORDER_DEFAULT);

opencv c语言教程,OpenCV图像处理视频教程——入门篇(一)相关推荐

  1. OpenCV图像处理视频教程——入门篇(二)

    文章目录 10 膨胀与腐蚀 (1)形态学操作(morphology operators)--膨胀.腐蚀 (2)相关API (3)动态调整结构元素大小TrackBar 11 形态学操作 (1)开操作- ...

  2. 数字图像处理(入门篇)目录

    目录: 1  数字图像处理(入门篇)一 图像的数字化与表示 2 数字图像处理(入门篇)二 颜色空间 3 数字图像处理(入门篇)三 灰度化 4 数字图像处理(入门篇)四 像素关系 5 数字图像处理(入门 ...

  3. opencv android安装教程,opencv for android安装教程.doc

    opencv for android安装教程 前言: ? ?最近android开发异常火热,随着手机性能越来越高,图像处程序也越来越重要, 由于opencv for android 网上教程大多为英文 ...

  4. keyshot渲染图文教程_Keyshot 渲染视频教程 入门到精通实用实例教材全套

    Keyshot 渲染视频教程 入门到精通实用实例教材全套 KeyShot 意为"The Key to Amazing Shots",是一个互动性的光线追踪与全域光渲染程序,无需复杂 ...

  5. keyshot手机渲染教程_Keyshot 渲染视频教程 入门到精通实用实例教材全套

    Keyshot 渲染视频教程 入门到精通实用实例教材全套 KeyShot 意为"The Key to Amazing Shots",是一个互动性的光线追踪与全域光渲染程序,无需复杂 ...

  6. 大话图像处理之入门篇

    本文从  http://c.biancheng.net/cpp/html/3077.html  转载而来.写的很深刻 最近有人问我图像处理怎么研究,怎么入门,怎么应用,我竟一时语塞.仔细想想,自己也搞 ...

  7. C语言学习书籍 零基础入门篇

    1.C语言入门很简单(配光盘)(入门很简单丛书) 2.零起点学通C语言(多媒体范例教学)(DVD)(C语言软件开发从零基础到精通) 3.C语言从入门到精通 4.啊哈C语言!逻辑的挑战(修订版)--20 ...

  8. 我对OpenGL教程的学习(入门篇)

    唠嗑: 做前端有小两年了,对自己使用的渲染技术却还是门外汉,这怎么说得过去,毕竟自己当初还是因为这神奇的技术才入了这个坑的呢. 关于OpenGL 我竟然都懒得去百度百科复制粘贴了.OpenGL其实是一 ...

  9. VBS带你领略脚本语言的快乐!(入门篇)

    VBS语言基础入门 前言    小弟初来乍到,自诩高中时曾自学过一点VBS脚本语言基础,感觉不错,想把学习到的东西记录下来,和大家分享一下,由于小弟我学艺不精,有误的地方还请多多指教.    入门篇是 ...

最新文章

  1. 图像、视频生成大一统!MSRA+北大全华班「女娲」模型怒刷8项SOTA,完虐OpenAI DALL-E...
  2. mac攻略(1) -- 简单配置php开发环境
  3. ResizeObserver - 元素resize监听API
  4. sqlserver主键自增
  5. python 修改pdf内容,如何使用python更改pdf内的超链接?
  6. 从排列与组合的python实现到生日问题的解释
  7. Q113:PBRT-V3分别在Linux和Mac下的编译与调试(汇总)
  8. 《算法竞赛入门经典》——刘汝佳
  9. 【016】随缘画-根据输入文字随机生成艺术画(带算法)
  10. 强化学习实战(九) Linux下配置星际争霸Ⅱ环境
  11. kail linux双系统win7,一步一步教你在Win7环境下安装Win7和Kali双系统
  12. php实现下雪场景,下雪的唯美短句 下雪的场景写一段话
  13. 【试算法题梳理】——二叉树
  14. LaTeX Warnings: Unused global option(s)
  15. C语言--逗号运算符及逗号表达式
  16. 推荐一款远程控制软件Toesk。支持文件传输、高清画质、隐私屏、键盘鼠标映射等功能。
  17. 软著 --- 注册与实名认证
  18. [译]Kotlin中是应该使用序列(Sequences)还是集合(Lists)?
  19. LoRa PHY CSS解调
  20. csdn使用Markdown

热门文章

  1. windows怎么用gpu跑python程序_在GPU(windows)上运行Theano的命令
  2. 最大子序列求和_连续子序列最大和与乘积问题的分析
  3. filter导致跨域失效_Quarkus中过滤器filter和跨域cors问题(4)
  4. oracle 编程必读_现在学习的编程语言,网络监视工具,备份解决方案以及更多必读内容
  5. 开源中国 精彩回顾_如何撰写精彩的事件回顾
  6. github 开放_GitHub为女性开发人员所做的工作,Tim O'Reilly谈开放数据等
  7. 太强大了 | 一键生成,太强大了……
  8. js 中的class
  9. Bootstrap3 折叠插件的使用方法
  10. Bootstrap3 动态模态对话框