//访问图像像素,使图像三通道分离
#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的使用和验证。
更多访问图像元素的方法请参考博客:http://blog.csdn.net/xiaowei_cqu/article/details/19839019
效果图: