【OpenCV】OpenCV常用函数(C++版)

俗话说:好记性不如烂笔头。在使用OpenCV的过程中,时常会用到很多函数,而且往往可能会一时记不起这个函数的具体参数怎么设置,故在此将常用函数做一汇总。


图像缩放与放大

对图像的各项操作中,放大或者缩小图像是最常见的操作之一。OpenCV提供resize函数来完成这项功能,其原型为:

void resize(InputArray src, OutputArray dst,
                        Size dsize, double fx = 0, double fy = 0,
                        int interpolation = INTER_LINEAR);

其中,src参数表示输入图像,dst参数表示输出图像,dsize参数表示输出图像的大小。如果这个参数不为0,那么就代表将原图像缩放到这个Size(width,height)指定的大小;如果这个参数为0,那么原图像缩放之后的大小就要通过下面的公式来计算

dsize = Size(round(fx ∗ src.cols), round(fy ∗ src.rows))

其中,fx和fy就是下面要说的两个参数,是图像width方向和height方向的缩放比例。fx:width方向的缩放比例,如果它是0,那么它就会按照(double)dsize.width/src.cols来计算;fy:height方向的缩放比例,如果它是0,那么它就会按照(double)dsize.height/src.rows来计算;interpolation参数表示插值的方式,图像缩放之后,肯定像素要进行重新计算的,就靠这个参数来指定重新计算像素的方式。

resize提供的插值方式包括:

插值方式含义
INTER_NEAREST最近邻插值
INTER_LINEAR线性插值(默认)
INTER_AREA区域插值
INTER_CUBIC三次样条插值
INTER_LANCZOS4Lanczos插值

如果想要了解这五种方式的区别和实现:OpenCV中resize函数五种插值算法的实现过程OpenCV图像缩放resize各种插值方式的比较

同时,使用resize函数需要注意以下几点:

  • dsize和fx/fy不能同时为0,要么指定好dsize的值,让fx和fy空置直接使用默认值,要么将dsize置零,指定fx和fy;
  • 插值方法,正常情况下使用默认的双线性插值就够用了,几种常用方法的效率是:最邻近插值>双线性插值>双立方插值>Lanczos插值。

一般在实际使用过程中,既可以通过resize来计算,也可以指定好输出图像的大小。例如:

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

int main(int argc, char const *argv[])
{
    cv::Mat frame_src = cv::imread("test.png", cv::IMREAD_GRAYSCALE);
    std::cout << "src: size " << frame_src.size[0] << " " << frame_src.size[1] << std::endl;

    cv::Mat frame_dest_1;
    cv::resize(frame_src, frame_dest_1, cv::Size(), 0.5, 0.5);
    std::cout << "dest_1: size " << frame_dest_1.size[0] << " " << frame_dest_1.size[1] << std::endl;

    cv::Mat frame_dest_2 = cv::Mat::zeros(512, 512, frame_src.type());
    cv::resize(frame_src, frame_dest_2, frame_dest_2.size());
    std::cout << "dest_2: size " << frame_dest_2.size[0] << " " << frame_dest_2.size[1] << std::endl;

    return 0;
}

图像数据类型转换

一般情况下,常用CV_8U来存放像素点,每个像素点的取值在0-255之间。但是有时候,也需要将每个像素点的取值转化成CV_32F、CV_8S等格式。OpenCV提供convertTo函数来实现,其定义为:

void convertTo(OutputArray m, int rtype, double alpha=1, double beta=0) const;

其中,m参数表示生成的输出图像,rtype参数表示输出图像的类型,由于convertTo不能修改通道数,所以rtype修改的是图像的位深度。如果rtype为负值,输入图像和输出图像将使用同样的类型。alpha参数表示尺度变换因子;beta参数表示附加到尺度变换后的值上的偏移量。

函数将输入图像中的像素值转换到输出图像。最后会使用溢出保护函数saturate_cast<>,以避免转换过程中可能出现的溢出。函数执行如下运算:

m(x, y) = saturate_cast < rtype> (alpha(*this)(x, y) + beta)

为什么使用溢出保护函数saturate_cast?

在像素值的计算过程中,由于尺度变换因子和偏移量的存在,可能使像素值超过其取值范围,这时候需要对其进行溢出保护。saturate_cast<>模板函数的原理如下,以CV_8U为例:

if (data < 0)
    data = 0;
else if (data > 255)
	data = 255;

例如:

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

int main(int argc, char const *argv[])
{
  cv::Mat frame_src = cv::imread("test.png", cv::IMREAD_GRAYSCALE);
  std::cout << "src: type " << frame_src.type() << " " << frame_src.elemSize1() << std::endl;

  cv::Mat frame_dest_3;
  frame_src.convertTo(frame_dest_3, CV_32F);
  std::cout << "dest_3: type " << frame_dest_3.type() << " " << frame_dest_3.elemSize1() << std::endl;

  return 0;
}

图像颜色空间转换

日常大多数看到的彩色图片都是RGB类型,但是在进行图像处理时,需要用到灰度图、二值图、HSV、HSI等颜色制式,OpenCV提供了cvtColor函数来实现这些功能。其函数定义为:

void cvtColor(InputArray src, OutputArray dst, int code, int dstCn = 0);

其中,src参数表示输入图像,dst参数表示输出图像,code参数表示颜色映射类型,通常格式为cv_xxx2xxx;dstCn参数表示输出图像的通道数,取0则表示由src和code来决定。

常见的颜色映射类型如:CV_GRAY2BGR、CV_BGR2GRAY、CV_BGR2RGB、CV_RGB2BGR等等。更多的颜色映射类型可以查看:opencv学习(十六)之颜色空间转换cvtColor()

例如:

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

int main(int argc, char const *argv[])
{
    cv::Mat frame_src = cv::imread("test.png", cv::IMREAD_GRAYSCALE);
    std::cout << "src: channel " << frame_src.channels() << std::endl;

    cv::Mat frame_dest_4;
    cv::cvtColor(frame_src, frame_dest_4, CV_GRAY2BGR);
    std::cout << "dest_4: channel " << frame_dest_4.channels() << std::endl;

    return 0;
}

图像通道分离与合并

在图像处理中,尤其是处理多通道图像时,有时需要对各个通道进行分离,分别处理;有时还需要对分离处理后的各个通道进行合并,重新合并成一个多通道的图像。OpenCV中实现图像通道的合并与分离的函数分别是splitmerge,其定义如下:

void split(const Mat& src, Mat* mvbegin);
void split(InputArray m, OutputArrayOfArrays mv);

void merge(const Mat* mv, size_t count, OutputArray dst);
void merge(InputArrayOfArrays mv, OutputArray dst);

其中,split函数的第一个参数表示输入图像,第二个参数表示分离的各通道数据;merge函数的第一个参数表示需要合并的各通道数据,第二个参数表示输出图像。

同时,在实际使用过程中,一般将分离后或待合并的多通道数据放在std::vector< Mat >中。例如:

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

int main(int argc, char const *argv[])
{
    cv::Mat frame_src = cv::imread("test.png", cv::IMREAD_GRAYSCALE);
    std::vector<cv::Mat> bgr_mat;
    cv::split(frame_src, bgr_mat);
    std::cout << bgr_mat.size() << std::endl;

    cv::Mat frame_src_1 = cv::imread("test.png", cv::IMREAD_COLOR);
    bgr_mat.clear();
    cv::split(frame_src_1, bgr_mat);
    std::cout << bgr_mat.size() << std::endl;

    bgr_mat.pop_back();
    cv::Mat frame_dest_5;
    cv::merge(bgr_mat, frame_dest_5);
    std::cout << frame_dest_5.channels() << std::endl;

    return 0;
}

图像翻转

图像翻转一般包括垂直翻转、水平翻转、水平垂直翻转三种。OpenCV提供了flip函数来实现,其函数定义为:

void flip(InputArray src, OutputArray dst, int flipCode);

其中,src参数表示输入图像,dst参数表示输出图像,flipCode参数表示翻转模式。flipCode=0垂直翻转(沿X轴翻转),flipCode>0水平翻转(沿Y轴翻转),flipCode<0水平垂直翻转(先沿X轴翻转,再沿Y轴翻转,等价于旋转180°)。

需要注意的是,flipCode是int类型,如果传入0.8会转换成0,沿X轴翻转,而不是沿Y轴翻转。因此,建议flipCode的取值-1、0、1。例如:

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

int main(int argc, char const *argv[])
{
    cv::Mat frame_src = cv::imread("test.png", cv::IMREAD_GRAYSCALE);

    cv::Mat frame_dest_6;
    cv::flip(frame_src, frame_dest_6, -1);

    return 0;
}

图像旋转

除了图像翻转之外,图像的旋转也许更加常见的操作。OpenCV提供需要先获得旋转矩阵,再根据旋转矩阵进行仿射变换来获得,其函数定义如下:

第一步,根据旋转中心和旋转角度获取旋转矩阵;

Mat getRotationMatrix2D(Point2f center, double angle, double scale);

其中,center参数表示旋转中心点,angle参数表示旋转角度,角度为正则表示逆时针旋转,角度为负表示逆时针旋转,scale参数表示缩放因子。

第二步,根据旋转矩阵进行仿射变换,实现图像旋转。

void warpAffine(InputArray src, OutputArray dst,
                    InputArray M, Size dsize,
                    int flags = INTER_LINEAR,
                    int borderMode = BORDER_CONSTANT,
                    const Scalar& borderValue = Scalar());

其中,src参数表示输入图像,dst参数表示输出图像,M参数表示变换矩阵,dsize参数表示输出图像的尺寸,flags表示插值算法标识符,borderMode参数表示边界像素模式,boderValue参数表示边界取值。

更多地了解OpenCV旋转内容,以及插值算法的种类可以查看:仿射变换warpAffine

例如:

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

int main(int argc, char const *argv[])
{
    cv::Mat frame_src = cv::imread("test.png", cv::IMREAD_GRAYSCALE);

    cv::Mat rot_mat = cv::getRotationMatrix2D(cv::Point2f(0, 0), 45, 1);
    cv::Mat frame_dest_7;
    cv::warpAffine(frame_src, frame_dest_7, rot_mat, frame_src.size());

    return 0;
}

图像滤波平滑

图像的滤波平滑处理很普遍,最主要的功能就是去噪声。在OpenCV中最经常使用的滤波平滑处理有四种:均值滤波、中值滤波、高斯滤波和双边滤波,OpenCV对它们也逐一进行了实现。其函数定义为:

//均值滤波
void blur(InputArray src, OutputArray dst,
                    Size ksize, Point anchor = Point(-1,-1),
                    int borderType = BORDER_DEFAULT);
//src参数表示输入图像,dst参数表示输出图像,与输入图像有同样的size和type;ksize参数表示核的大小
//anchor参数表示核的中心,默认值为Point(-1,-1),会转化为核的中点;borderType参数表示边缘点插值类型

//中值滤波
void medianBlur(InputArray src, OutputArray dst, int ksize);
//src参数表示输入图像,dst参数表示输出图像,与输入图像有同样的size和type;ksize参数表示正方形的边长. 边长必须是奇数而且大于1
//需要注意的是,当ksize是3或5的时候,图像的深度可以是CV_8U、CV_16U或CV_32F,对于更大的ksize,那么图像的深度只能是CV_8U

//高斯滤波
void GaussianBlur(InputArray src, OutputArray dst, Size ksize,
                    double sigmaX, double sigmaY = 0,
                    int borderType = BORDER_DEFAULT);
//src参数表示输入图像,dst参数表示输出图像,与输入图像有同样的size和type;ksize参数表示高斯核大小
//ksize.width和ksize.height可以不同,但是都必须是正整数而且是奇数,也可以是O,如果是0的话,它的值由sigmaX和sigmaY决定
//sigmaX参数表示X方向上的标准差,sigmaY参数表示Y方向上的标准差,如果Y方向为0,则被设置和X方向一样,如果X和Y方向都为0,则它们由ksize.width和ksize.height计算得到,建议全部都给定数值。
//borderType参数表示边缘点插值类型

//双边滤波器
void bilateralFilter( InputArray src, OutputArray dst, int d,
                    double sigmaColor, double sigmaSpace,
                    int borderType = BORDER_DEFAULT );
//src参数表示输入图像为单通道或3通道的8比特图像,dst参数表示输出图像,与输入图像有同样的size和type
//d参数表示每个像素领域的直径,如果为负数,则由sigmaSpace确定
//sigmaColor参数表示颜色空间的标准偏差,sigmaSpace表示坐标空间的标准偏差,borderType参数表示边缘点插值类型

如果想要深入查看几种滤波方式的内容,可以查看:图像平滑处理

例如:

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

int main(int argc, char const *argv[])
{
    cv::Mat frame_src = cv::imread("test.png", cv::IMREAD_GRAYSCALE);

    cv::Mat frame_dest_8;
    cv::blur(frame_src, frame_dest_8, cv::Size(3, 3));
    cv::medianBlur(frame_src, frame_dest_8, 3);
    cv::GaussianBlur(frame_src, frame_dest_8, cv::Size(3, 3), 0, 0);
    cv::bilateralFilter(frame_src, frame_dest_8, 4, 2, 2);

    return 0;
}
OpenCV 是一个开源的计算机视觉和机器学习软件库,它包含众多的计算机视觉和图像处理算法。在 OpenCV 中,`resize` 函数是用来改变图像大小的标准函数。 `resize` 函数可以将原始图像调整到指定的尺寸,可以用来减小图像以加快处理速度或者用于某些特定的图像处理任务,如图像缩略图的生成等。它也可以用来放大图像,尽管这可能会导致图像质量下降。 函数的基本语法如下: ```cpp void cv::resize( InputArray src, OutputArray dst, Size dsize, double fx = 0, double fy = 0, int interpolation = INTER_LINEAR ); ``` 其中参数的含义如下: - `src`:输入图像,即要调整大小的原始图像。 - `dst`:输出图像,即调整大小后的图像。 - `dsize`:目标图像的大小。 - `fx` 和 `fy`:可选参数,分别表示水平方向和垂直方向的缩放因子,如果提供了这两个参数,`dsize` 将被忽略。 - `interpolation`:可选参数,插值方法,常用的有 `INTER_LINEAR`(双线性插值)和 `INTER_NEAREST`(最近邻插值)等。 `resize` 函数支持多种插值方法,不同的插值方法适用于不同的场景,例如: - `INTER_LINEAR`:双线性插值,适合连续色调的图片缩放,速度适中。 - `INTER_NEAREST`:最近邻插值,适合缩放精度要求不高的图片,速度快。 - `INTER_CUBIC`:双立方插值,适合缩放时保留更多细节,但计算量更大。 使用 `resize` 函数时要注意选择合适的插值方法和缩放比例,以确保最终的图片质量满足需求。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值