您的位置:首页 > 运维架构

opencv笔记 3.访问图像元素的四种方法

2015-11-12 21:50 531 查看
//访问图像像素,使图像三通道分离
#include<iostream>
#include<cv.hpp>
using namespace cv;
using namespace std;

//声明四种最常用,简单的访问像素的方法
void bluechannel(Mat ROI, Mat outputImage);
void greenchannel(Mat ROI, Mat outputImage);
void redchannel(Mat ROI, Mat outputImage);
void channel(Mat inputImage, Mat outputImage);

int main()
{
//定义三个Mat变量
Mat srcimage = imread("1.jpg");
Mat logo = imread("2.jpg");
Mat outputImage;
//namedWindow("混合图", WINDOW_NORMAL);

//融合图像并显示
Mat ROI = srcimage(Rect(500, 200, logo.cols, logo.rows));
addWeighted(logo, 0.8, ROI, 0.4, 0, ROI);
//上面两行代码可以用下面一行代替
//addWeighted(logo, 0.2, srcimage(Rect(500, 200, logo.cols, logo.rows)), 0.8, 0, srcimage(Rect(500, 200, logo.cols, logo.rows)));
imshow("混合图", srcimage);
imshow("原图", ROI);

/***********************此处代码为split函数的测试与验证***********************
vector<Mat> channels;
split(ROI, channels);                            //使用函数进行通道分离

Mat test= channels.at(1);                        //把分离出来的第一通道赋给test,此时test为单通道图像
cvtColor(logo,logo,CV_RGB2GRAY);                 //RGB灰度转换为灰度图像,使三通道变为一通道,进行下面的融合。融合必须注意两图像的尺寸和深度(通道)

addWeighted(test, 0.8, logo, 0.4, 0, logo);
imshow("混合图1", logo);

channels.at(0) = 0;
merge(channels, ROI);   imshow("混合图2", ROI);
*/

//四种方法的调用函数
bluechannel(ROI, outputImage);
greenchannel(ROI, outputImage);
redchannel(ROI, outputImage);
channel(ROI, outputImage);

waitKey();
return 0;
}

//矩阵元素访问的四种方法:指针、迭代器和动态地址计算法
//1.分离蓝色通道——用指针访问像素
void bluechannel(Mat inputImage, Mat outputImage)
{
outputImage = inputImage.clone();
int nrow = outputImage.rows;
int ncol = outputImage.cols * outputImage.channels();
for (int i = 0; i<nrow; i++){
uchar* data = outputImage.ptr<uchar>(i);        //指针指向每一行的开头
for (int j = 0; j<ncol; j++)
{
if (j % 3 != 0)                                 //一二通道像素为0,对第三通道数据不作处理
data[j] = 0;
}
}
imshow("蓝色通道图", outputImage);

}

//2.分离绿色通道——用迭代器访问像素
void greenchannel(Mat inputImage, Mat outputImage)
{
outputImage = inputImage.clone();

Mat_<Vec3b>::iterator itbegin = outputImage.begin<Vec3b>();
Mat_<Vec3b>::iterator itend = outputImage.end<Vec3b>();

//三通道处理
for (; itbegin != itend; itbegin++)
{
(*itbegin)[0] = 0;
(*itbegin)[1] = (*itbegin)[1];
(*itbegin)[2] = 0;
}
imshow("绿色通道图", outputImage);

}

//3.分离红色通道——用动态地址计算访问像素
void redchannel(Mat inputImage, Mat outputImage)
{
outputImage = inputImage.clone();
//三通道处理
for (int i = 0; i<outputImage.rows; i++)
for (int j = 0; j<outputImage.cols; j++)
{
outputImage.at<Vec3b>(i, j)[0] = 0;
outputImage.at<Vec3b>(i, j)[1] = 0;
outputImage.at<Vec3b>(i, j)[2] = outputImage.at<Vec3b>(i, j)[2];
}
imshow("红色通道图", outputImage);

}

//4.三通道全为零——用下标法访问像素(指针法)
void channel(Mat inputImage, Mat outputImage)
{
outputImage = inputImage.clone();
//uchar* data = outputImage.data;
uchar* data = outputImage.ptr();    // 这行和上行代码功能相同,使指针指向图像存储区的开头
int step = outputImage.step;
for (int i = 0; i<outputImage.rows; i++)
for (int j = 0; j < outputImage.cols; j++)
{
data[i*step + j*outputImage.channels() + 0] = 0;
data[i*step + j*outputImage.channels() + 1] = 0;
data[i*step + j*outputImage.channels() + 2] = 0;
}

imshow("三通道全为零", outputImage);

}


本文写了四种最简单,直接,容易理解的四种访问图像元素方法,并通过图像的三通道分离进行了举例说明。其中星号注释的部分是对opencv提供的库函数split的使用和验证。

更多访问图像元素的方法请参考博客:/article/1357495.html

效果图:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: