OpenCV3入门(四)图像的基础操作

2019/04/10 10:10
阅读数 19

1、访问图像像素

1)灰度图像

2)彩色图像

OpenCV中的颜色顺序是BGR而不是RGB。

访问图像的像素在OpenCV中就是访问Mat矩阵,常用的有三种方法。

  •  at定位符访问

Mat数据结构,操作灰度图像像素点:

int gray_value = (int) image.at<uchar>(i , j) ;

操作彩色图像像素点:

int color_value = (int) image.at<Vec3b>(i , j) [k];

  • 指针访问
for (int i = 0; i < mat.rows; i++)
{
    uchar* row = mat.ptr<uchar>(i); // 行指针
    for (int j = 0; j < mat.cols; j++) // 遍历每一行
    {
        row[j] = (uchar)((j / 5) * 10); 
    }
}
  • 迭代器iterator访问
Mat_<Vec3b>::iterator it = M.begin<Vec3b>();//初始位置的迭代器
Mat_<Vec3b>::iterator itend = M.end<Vec3b>();//终止位置的迭代器
for (; it != itend; it++)
{
    //处理BGR三个通道
    (*it)[0] = 182;//B
    (*it)[1] = 194;//G
    (*it)[2] = 154;//R
}

2、图像亮度、对比度调节

图像亮度调节可以等效为图像的像素操作。如下面公式是一个线性的亮度调节。

g(x)=a*f(x) + b

其中:

g(x):处理后的图像

f(x):输入图像

a:增益(放大倍数),用来控制图像的对比度

b:偏置,用控制图像的亮度

Mat M = imread("D:/WORK/5.OpenCV/LeanOpenCV/pic_src/pic4.bmp", IMREAD_GRAYSCALE);
Mat M2 = Mat(M.rows, M.cols, CV_8UC1);
cout << M.channels() << endl;
cout << M.rows<<","<<M.cols << endl;

float a = 0.5;
float b = 10;
for (int i = 0; i < M.rows; i++)
    for (int j = 0; j < M.cols; j++)
    {
        float pix = (float)M.at<uchar>(i, j);
        pix = a * (float)pix + b;
        if ((int)pix > 255) pix = 255;
        M2.at<uchar>(i, j) = (uchar) pix;
    }

imshow("pic1", M);
imshow("pic2", M2);
waitKey(0);

3、获取图像ROI区域

图像的ROI(region of interest)是指图像中感兴趣区域、在OpenCV中图像设置图像ROI区域,实现对ROI区域操作。

方法1:

img(Rect(100, 100, 100, 100));

Rect代表一个矩形,Rect_ (_Tp _x, _Tp _y, _Tp _width, _Tp _height),参数分别是x,y,width,height。

方法2:

img(Range(100, 200), Range(100,200));

Range表示连续的行或列,Range (int _start, int _end);

示例:

Mat M = imread("D:/WORK/5.OpenCV/LeanOpenCV/pic_src/pic1.bmp");
cout << M.rows<<","<<M.cols << endl;
Mat roi = M(Rect(30, 50, 150, 170));

imshow("pic1", M);
imshow("roi", roi);

4、图像混合

图像线性混合,产生类似画中画的效果。

h(x)=(1-a)*f(x) + b*g(x)

a的取值范围为0到1之间,通过对两幅图的像素加权得到最终的输出图像,两幅图像的大小和类型必须完全一致(两个矩阵相加维度必须一致)。

CV_EXPORTS_W void addWeighted(InputArray src1, double alpha, InputArray src2,

                   double beta, double gamma, OutputArray dst, int dtype = -1);

例1:图片与背景图混合

Mat M = imread("D:/WORK/5.OpenCV/LeanOpenCV/pic_src/pic1.bmp");
cout << M.rows<<","<<M.cols << endl;
Mat y(M.rows, M.cols, CV_8UC3, Scalar(0, 50, 100));
Mat dst;
addWeighted(M, 0.3, y, 0.7, 0.0, dst);

imshow("pic1", M);
imshow("y", y);
imshow("add", dst);

例2:两幅图像混合,先统一尺寸

Mat M = imread("D:/WORK/5.OpenCV/LeanOpenCV/pic_src/pic1.bmp");
Mat M2 = imread("D:/WORK/5.OpenCV/LeanOpenCV/pic_src/pic2.bmp");
M2 = M2(Rect(0, 0, M.cols, M.rows)); //x,y,width,height
cout << M.rows<<","<<M.cols << endl;
cout << M2.rows << "," << M2.cols << endl;
Mat dst;
addWeighted(M, 0.7, M2, 0.3, 0.0, dst);

imshow("pic1", M);
imshow("pic2", M2);
imshow("add", dst);

5、图像多通道分离

1)函数原型

/** @brief Divides a multi-channel array into several single-channel arrays.
@param src input multi-channel array.
@param mvbegin output array; the number of arrays must match src.channels(); the arrays themselves are reallocated, if needed.
*/
CV_EXPORTS void split(const Mat& src, Mat* mvbegin);

/** @overload
@param m input multi-channel array.
@param mv output vector of arrays; the arrays themselves are reallocated, if needed.
*/

2)图像颜色通道

Mat M = imread("D:/WORK/5.OpenCV/LeanOpenCV/pic_src/pic5.bmp");
vector<Mat> channels;
split(M, channels);

imshow("pic1", M);
imshow("B", channels.at(0));
imshow("G", channels.at(1));
imshow("R", channels.at(2));
/* 方法2
Mat channels[3];
split(M, channels);

imshow("pic1", M);
imshow("B", channels[0]);
imshow("G", channels[1]);
imshow("R", channels[2]);

 6、图像多通道合并

图像合并函数mergesplit的逆操作,将多个数组合并成多通道的数组。

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

merge(InputArrayOfArrays mv, OutputArray dst )      

//图像合并例子,方式1:
Mat M = imread("D:/WORK/5.OpenCV/LeanOpenCV/pic_src/pic5.bmp");
Mat channels[3];
split(M, channels);

imshow("pic1", M);
imshow("B", channels[0]);
imshow("G", channels[1]);
imshow("R", channels[2]);

Mat dst;
merge(channels, 3, dst);
imshow("merged", M);
//方式2:
Mat M = imread("D:/WORK/5.OpenCV/LeanOpenCV/pic_src/pic5.bmp");
vector<Mat> channels;
split(M, channels);

imshow("pic1", M);
imshow("B", channels.at(0));
imshow("G", channels.at(1));
imshow("R", channels.at(2));

Mat dst;
merge(channels, dst);
imshow("merged", M);

输出如下图。

7、参考文献

1、《OpenCV3 编程入门》,电子工业出版社,毛星雨著

2、《学习OpenCV》,清华大学出版社,Gary Bradski Adrian kaehler

3opencv常用api简单分析: split()merge()

 

尊重原创技术文章,转载请注明。

 https://www.cnblogs.com/pingwen/p/12296617.html

原文出处:https://www.cnblogs.com/pingwen/p/12296617.html

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部