OpenCV图像处理视频教程——入门篇(一)

OpenCV图像处理视频教程基础篇
摘要由CSDN通过智能技术生成

OpenCV图像处理视频教程

---------------------------------------🤣 🤩 🤪 🧐 🤯 🥳 🤨 🥰 🤔 --------------------------------------------------
Author: XFFer_


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

concept

  • HighGUI部分
  • Image Process
  • 2D Feature
  • Camera Calibration and 3D reconstruction
  • Video Analysis
  • Object Detection
  • Machine Learning
  • GPU加速

02 加载、修改、保存图像

  • 加载图像(用cv::imread)
  • 修改图像(cv::cvtColor)
  • 保存图像(cv::imwrite)
  • 代码演示

(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格式的时候可以保存透明通道的图片
  • 可以指定压缩参数

03 矩阵的掩膜操作

1 获取图像像素指针
2 掩膜操作解释
3 代码演示

(1)获取图像像素指针

  • CV_Assert(myImage.depth() == CV_8U);测试位图深度是否为8位,如果False则停止运行
    • 位图深度:在灰度图像中8位代表从黑(0)到白(1)分为256个颜色深度;在RGB图像中代表每个通道(每个原色)都分为256个子色,总体上为256 * 256 * 256种颜色
  • Mat.ptr<uchar>(int i = 0)(uchar是unsigned char,一个字节0~ 255,像素值也是在0~255)获取像素矩阵的指针,索引i表示第几行,从0开始计行数
  • 获得当前行指针const uchar* current = myImage.ptr<uchar>(row);
  • 获取当前像素点P(row, col)的像素值p(row, col) = current[col];

(2)像素范围处理saturate_cast

  • saturate_cast<uchar>(-100),返回0
  • saturate_cast<uchar>(288),返回255
  • saturate_cast<uchar>(124),返回124
  • 这个函数的功能是确保RGB值的范围在0~255之间

(3)掩膜操作解释

在这里插入图片描述

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

在这里插入图片描述
这是一张3*3的(255, 0, 0)的纯红色图片
在这里插入图片描述
(.ptr<uchar>(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_<char>(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等。

在这里插入图片描述

04 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_8UC2CV_8UC3(彩色BGR)、CV_8UC4(带透明色的BGR)都是Unsigned 8bits
      • CV_32FC1CV_32FC2CV_32FC3是float32位
      • CV_64FC1CV_64FC2CV_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_<typename>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);

05 图像操作

1 读写图像
2 读写像素
3 修改像素值

(1)读写像素

  • 读一个GRAY像素点的像素值(CV_8UC1)
    • int intensity = img.at<uchar>(row, col);
    • int intensity = img.at<uchar>(Point(row, col));
  • 读一个RGB像素点的像素值(CV_8UC3)
    • Vec3f intensity = img.at<Vec3b>(row, col); Vec3b -> 返回值是unsigned char
    • int blue = intensity.val[0];
      int blue = img.at<Vec3b>(row, col)[0]; 这种写法也是对的 blue
    • int green = intensity.val[1]; green
    • int red = intensity.val[2]; red
.ptr(row)[col]和.at(row, col)[channel]的区别:
  • .ptr<uchar>(row)[col]是在一个已展开的图像上提取像素指针,对于多通道而言(BGR三通道ptr获取像素指针时,每个位置三个通道是排开的,可以理解为一个像素位置由三个字节构成)
    • 它的返回值类型为const _Tp * ptr<_Tp, n>(const cv::Vec<int, n> &idx) const
  • .at<uchar>(row, col)[channel]是在原图像位置上取出像素指针,通过[channel]获取不同通道下的像素指针的
    • 它的返回值类型为const _Tp &at<_Tp>(cv::Point pt) const
对各通道取反操作API

bitwise_not(input_img, output_img);

编译器快捷键
选中代码后Alt + 方向键 移动代码块

06 图像混合

1 理论-线性混合操作
2 相关API(addWeighted)
3 代码演示

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

g ( x ) = ( 1 − α ) f 0 ( x ) + α f 1 ( x ) g(x) = (1 - \alpha )f_{0}(x) + \alpha f_{1}(x) g(x)=(1α)f0(x)+αf1(x)
其中 α \alpha α的取值范围为0~1之间。

(2)相关API(addWeighted)

void cv::addWeighted ( InputArray	src1,
					   double		alpha,
					   InputArray   src2,
					   double		beta,
					   double		gamma,
					   OutputArray  dst,
					   int 			dtype = -1
					 )

d s t ( I ) = s a t u r a t e ( s r c 1 ( I ) ∗ α + s r c 2 ( I ) ∗ β + γ ) ( β = 1 − α ) dst(I) = saturate(src1(I) * \alpha + src2(I) * \beta + \gamma)(\beta = 1-\alpha) dst(I)=saturate(src1(I)α+src2(I)β+γ)(β=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内的计时周期数)
    • g e t T i c k C o u n t
  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值