OpenCV颜色分离与访问像素


一、颜色通道

1.通道分离:split()

原型

void split(
	InputArray m,
	OutputArrayOfArrays mv;
)

参数

  • m:要进行分离的图像
  • mv:输出的通道容器。一般是vector<Mat>容器

例子:分离三通道

Mat srcIamge=imread();
vector<Mat> channels;
split(srcImage,channels);
//使用at()来得到BGR的
Mat dstImageBlue=channels.at(0);
Mat dstImageGreen=channels.at(1);
Mat dstImageRed=channels.at(2);

2.通道合并merge()

原型

void merge(
	InputArrayOfArrays mv;
	OutputArray dst
)

参数

  • mv:输入的通道容器。一般是vector<Mat>容器
  • dst:合成的图像

例子:分离三通道

Mat dstImage;
merge(channels,dstImage);

二、效果

#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;

String windowNames[]={"Blue","Green","Red"};
String trackbarNames[]={"ThresholdbarBlue","ThresholdbarGreen","ThresholdbarRed"};


Mat g_srcImage;

Mat g_dstImageBlue;
Mat g_dstImageGreen;
Mat g_dstImageRed;

Mat g_dstImageBlueThreshold;
Mat g_dstImageGreenThreshold;
Mat g_dstImageRedThreshold;

int g_dstImageBlueThresholdValue=0;
int g_dstImageGreenThresholdValue=0;
int g_dstImageRedThresholdValue=0;

const int g_dstImageThresholdValueMax=255;

vector<Mat> g_channels;

void mySplit()
{

    split(g_srcImage,g_channels);
    g_dstImageBlue=g_channels.at(0);
    g_dstImageGreen=g_channels.at(1);
    g_dstImageRed=g_channels.at(2);
}

void onChange(int,void*)
{
    //deep copy
    g_dstImageBlue.copyTo(g_dstImageBlueThreshold);
    g_dstImageGreen.copyTo(g_dstImageGreenThreshold);
    g_dstImageRed.copyTo(g_dstImageRedThreshold);
    
    //Threshold
    g_dstImageBlueThreshold=g_dstImageBlueThreshold>g_dstImageBlueThresholdValue;
    g_dstImageGreenThreshold=g_dstImageGreenThreshold>g_dstImageGreenThresholdValue;
    g_dstImageRedThreshold=g_dstImageRedThreshold>g_dstImageRedThresholdValue;

    //show
    imshow(windowNames[0],g_dstImageBlueThreshold);
    imshow(windowNames[1],g_dstImageGreenThreshold);
    imshow(windowNames[2],g_dstImageRedThreshold);
}

int main()
{
    g_srcImage=imread("M.jpg");
    GaussianBlur(g_srcImage,g_srcImage,Size(61,61),0.0);
    
    //split channels
    mySplit();

    //Window
    namedWindow(windowNames[0],WINDOW_NORMAL);
    namedWindow(windowNames[1],WINDOW_NORMAL);
    namedWindow(windowNames[2],WINDOW_NORMAL);

    //createTrackbar
    createTrackbar(trackbarNames[0],windowNames[0],&g_dstImageBlueThresholdValue,g_dstImageThresholdValueMax,onChange);
    createTrackbar(trackbarNames[1],windowNames[1],&g_dstImageGreenThresholdValue,g_dstImageThresholdValueMax,onChange);
    createTrackbar(trackbarNames[2],windowNames[2],&g_dstImageRedThresholdValue,g_dstImageThresholdValueMax,onChange);
    onChange(0,0);

	waitKey();
	return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、访问像素

1.单位

这个单位T就是Mat的通道深度类型:OpenCV3之Mat类的类型type和深度depth

2.方法

在这里插入图片描述
因为图像是以左上角为原点,所以x对应j(列),y对应i(行)。

(1)at动态地址计算

①i单下标

把每行拼接成一行算。

Mat A = (Mat_<uchar>(2,2)<<0,1,2,3);
cout << A << endl;
/**
[  0,   1;
   2,   3]
 */
 
// 第0个
printf("%d\n",A.at<uchar>(0));
// 0

// 第3个
printf("%d\n",A.at<uchar>(3));
// 3
②i、j行列双下标

格式:

  • 单通道:image.at<T>(i,j)
  • 多通道:image.at<Vec<T,n> >(i,j)[channel],比如image.at<Vec3b>(0,0)[0]三通道图像左上角第0通道
    这个[]不是什么特殊的意思,这个就是Vec向量的数组下标访问。

遍历方式像遍历数组一样,是从上往下遍历每一行,对应image.at<Vec3b>(i,j)。但需要注意的at(i,j)对应图像的at(y,x),

在这里插入图片描述
如:读取一副彩色图像,选择红光的区域。将其区域的分离出来,做成一张二值图

#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;

int main()
{
    Mat srcImage=imread("S1.jpg");
    //dstImage必须创建,要不然无法访问。
    //这里的CV_8UC1表示单通道图
    Mat dstImage=Mat::zeros(srcImage.size(),CV_8UC1);

    //遍历方式是从上往下遍历每一行
    for(int i=0;i<dstImage.rows;i++)
    {
        for(int j=0;j<dstImage.cols;j++)
        {
            //srcImage是三通道图,所以用Vec3b
            //选择红光:R>200,G<150,B<150
            if(srcImage.at<Vec3b>(i,j)[0]<150 && srcImage.at<Vec3b>(i,j)[1]<150 && srcImage.at<Vec3b>(i,j)[2]>200)
            {
                //dstImage是单通道图,所以用uchar
                dstImage.at<uchar>(i,j)=255;
            }
        }
    }
    namedWindow("BGR",WINDOW_NORMAL);
    imshow("BGR",dstImage);

    waitKey();
    return 0;
}

在这里插入图片描述
在这里插入图片描述

(2)迭代器

格式:

//定义
Mat_<T>::iterator begin=image.begin<T>()
Mat_<T>::iterator end=image.end<T>()

//使用
(*it)[channel]

如:

#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;

int main()
{
    Mat srcImage=imread("S1.jpg");
    //dstImage必须创建,要不然无法访问。
    //这里的CV_8UC1表示单通道图
    Mat dstImage=Mat::zeros(srcImage.size(),CV_8UC1);

    Mat_<Vec3b>::iterator it=srcImage.begin<Vec3b>();
    Mat_<Vec3b>::iterator itend=srcImage.end<Vec3b>();

    Mat_<uchar>::iterator dst=dstImage.begin<uchar>();

    //遍历方式是从上往下遍历每一行
    for(;it<itend;it++,dst++)
    {
        //srcImage是三通道图,所以用Vec3b
        //选择红光:R>200,G<150,B<150
        if((*it)[0]<150 && (*it)[1]<150 && (*it)[2]>200)
        {
            //dstImage是单通道图,所以用uchar
            (*dst)=255;
        }
    }
    namedWindow("dst",WINDOW_NORMAL);
    imshow("dst",dstImage);

    waitKey();
    return 0;
}

在这里插入图片描述

(3)指针

格式:

T* data=image.ptr<T>(i);	//行循环中:获取第i行的首地址
data[j];					//每行中的列循环中:获取像素的地址

如:

#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;

int main()
{
    Mat srcImage=imread("S1.jpg");
    //dstImage必须创建,要不然无法访问。
    //这里的CV_8UC1表示单通道图
    Mat dstImage=Mat::zeros(srcImage.size(),CV_8UC1);


    //遍历方式是从上往下遍历每一行
    for(int i=0;i<srcImage.rows;i++)
    {
        //srcImage是三通道图,所以用Vec3b
    	Vec3b* src=srcImage.ptr<Vec3b>(i);
        //dstImage是单通道图,所以用uchar
        uchar* dst=dstImage.ptr<uchar>(i);

        for(int j=0;j<dstImage.cols;j++)
        {
            //srcImage是三通道图,所以用Vec3b
            //选择红光:R>200,G<150,B<150
            if(src[j][0]<150 && src[j][1]<150 && src[j][2]>200)
            {
                dst[j]=255;
            }
        }
    }
    namedWindow("dst",WINDOW_NORMAL);
    imshow("dst",dstImage);

    waitKey();
    return 0;
}

在这里插入图片描述

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值