OpenCV(5)通道分离合并 色彩空间转换 像素值统计 C++

18 篇文章 9 订阅

1. OpenCV通道分离与合并

1.1.(cv :: split) 把一幅图像各个通道分离开

CV_EXPORTS_W void split(InputArray m, OutputArrayOfArrays mv);
  • m:输入多通道阵列。输入一副多通道图片
  • mv:数组输出向量;如果需要,将重新分配数组本身。

1.2.(cv :: merge) 把一幅图像各个通道合并

CV_EXPORTS_W void merge(InputArrayOfArrays mv, OutputArray dst);
  • mv:待合并矩阵的输入向量;mv中的所有矩阵必须是相同的大小和深度相同。
  • dst:与mv[0]相同大小和深度的DST输出数组;频道的数量会为矩阵数组中通道的总数。
#include "opencv2\opencv.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
    Mat src = imread("../data/test2.jpg");
    if (src.empty())
    {
        printf("Could not load image...\n");
        return -1;
    }
    namedWindow("SrcImg", WINDOW_AUTOSIZE);
    imshow("SrcImg", src);
    vector<Mat> mv;
    Mat dstBlue, dstGreen, dstRed;
    //分离图片的BGR通道图片至Vector
    //以下分别对B、G、R进行赋值操作(将对应通道的颜色赋值为0,即去除该颜色),再进行通道合并
    //如果分别对B、G、R进行赋值操作(将对应通道的颜色赋值为255,则整个图片将显示偏"B\G\R"色)
    split(src, mv);
    mv[0] = Scalar(0);
    //mv[1] = Scalar(0);//此时整个图片的BG通道均为0,图片整体颜色偏红R
    merge(mv, dstBlue);
    split(src, mv);
    mv[1] = Scalar(0);
    merge(mv, dstGreen);
    split(src, mv);
    mv[2] = Scalar(0);
    merge(mv, dstRed);
    //显示操作结果
    imshow("DstB", dstBlue);
    imshow("DstG", dstGreen);
    imshow("DstR", dstRed);
    waitKey(0);
    return 0;
}
//inrange可以提取特定颜色

执行结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 色彩空间与色彩空间转换

  • 蓝色:值分布在[110,100,100]~[130,255,255]之间
  • 绿色:值分布在[50,100,100]~[70,255,255]之间
  • 红色:值分布在[0,100,100]~[10,255,255]之间

2.1.各颜色对应的范围

在这里插入图片描述

2.2.(cv :: cvtColor)色彩空间转换

CV_EXPORTS_W void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 );
  • src:输入图像:8位无符号,16位无符号(CV_16UC…),或者单精度浮点。
  • dst:输出图像的大小和深度与src相同。
  • code:颜色空间转换代码(见#ColorConversionCodes)。
  • dstCn:目标图像中的通道数量;当参数为0时,序号为通道自动从SRC和代码派生。
#include "opencv2\opencv.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
    Mat src = imread("../data/test3.jpg");
    if (src.empty())
    {
        printf("Could not load image...\n");
        return -1;
    }
    //色彩空间转换
    Mat yuvImg, hsvImg, ycrcbImg;
    cvtColor(src, yuvImg, COLOR_BGR2YUV);
    cvtColor(src, hsvImg, COLOR_BGR2HSV);
    cvtColor(src, ycrcbImg, COLOR_BGR2YCrCb);
    //图像显示
    imshow("YUV", yuvImg);
    imshow("HSV", hsvImg);
    imshow("YCRCB", ycrcbImg);
    waitKey(0);
    return 0;
}

执行结果:
在这里插入图片描述

2.3.(cv :: inRange)色彩空间转换

C++:

void inRange(InputArray src, InputArray lowerb, InputArray upperb, OutputArray dst)

C:

void cvInRangeS(const CvArr* src, CvScalar lower, CvScalar upper, CvArr* dst) 
  • src:输入图像,CV2常用Mat类型;
  • lowerb:lower boundary下限,scalar类型的像素值,单通道scalar取一个值就行,彩图3通道scalar三个值;
  • upperb:上限,类型与lowerb同理;
  • dst:输出图像,尺寸与src一致,类型是CV_8U,但没有指定通道数。
    对于多通道的输入,输出结果是各个通道的结果相与,当各通道结果都在上下限之内时,输出为255,否则为0。因此也有人将输出理解为掩码模板!

2.4.(cv :: blur)均值滤波

C++:

void blur(InputArray src, OutputArray dst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT )
  • src:源图像,填Mat类的对象即可
  • dst:即目标图像,需要和源图片有一样的尺寸和类型。比如可以用Mat::Clone
  • ksize:内核的大小。一般这样写Size( w,h )来表示内核的大小,w 为像素宽度 h为像素高度
  • anchor:表示锚点(即被平滑的那个点),注意他有默认值Point(-1,-1)。如果这个点坐标是负值的话,就表示取核的中心为锚点,所以默认值Point(-1,-1)表示这个锚点在核的中心。
  • borderType:用于推断图像外部像素的某种边界模式。有默认值BORDER_DEFAULT,我们一般不去管它。

2.5.(cv :: medianBlur)中值滤波

C++:

void medianBlur(InputArray src, OutputArray dst, int ksize)
  • src:
    输入图像,图像为1、3、4通道的图像,当模板尺寸为3或5时,图像深度只能为CV_8U、CV_16U、CV_32F中的一个,如而对于较大孔径尺寸的图片,图像深度只能是CV_8U。
  • dst: 输出图像,尺寸和类型与输入图像一致,可以使用Mat::Clone以原图像为模板来初始化输出图像dst
  • ksize: 滤波模板的尺寸大小,必须是大于1的奇数,如3、5、7……
#include "opencv2\opencv.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{ 
    Mat getColorImg, getMask, getMask1;
    getColorImg = imread("../data/test3.jpg");
    //imshow("MyPhoto", getColorImg);
    cvtColor(getColorImg, getColorImg, COLOR_BGR2YUV);//颜色提取需要先转换为HSV颜色空间
    //That is, dst (I) is set to 255 (all 1 -bits) if src (I) is within the
    //specified 1D, 2D, 3D, ... box and 0 otherwise.
    inRange(getColorImg, Scalar(100, 43, 46), Scalar(124, 255, 255), getMask);//蓝色范围内的颜色转换为255,其他为0
    blur(getMask, getMask1, Size(1, 1));//均值滤波会使边缘变得模糊
    imshow("GetMask1", getMask1);
    medianBlur(getMask, getMask, 1);//中值滤波对边缘轮廓影响较小
    imshow("GetMask", getMask);
    waitKey(0);
    return 0;
}

执行结果:
均值滤波、中值滤波:
在这里插入图片描述

3.图像像素值统计

用途:统计直方图;求取图像像素最大值、最小值,对图像进行归一化;求取图像均值、方差,进行分割或归一化;根据方差判断图像中信息量多少(若方差很小则说明图像像素间差异小,有效信息少);
两个API:

3.1.(cv :: minMaxLoc)查找元素的最小值和最大值及其位置

CV_EXPORTS_W void minMaxLoc(InputArray src, CV_OUT double* minVal,
                            CV_OUT double* maxVal = 0, CV_OUT Point* minLoc = 0,
                            CV_OUT Point* maxLoc = 0, InputArray mask = noArray());
  • src::输入单通道数组。
  • minVal:指针返回的最小值; 如果不需要,则使用NULL。
  • maxVal:指针指向返回的最大值; 如果不需要,则使用NULL。
  • minLoc:指针指向返回的最小位置(在2D情况下); 如果不需要,则使用NULL。
  • maxLoc:指针,指向返回的最大位置(在2D情况下);如果不需要,则使用NULL。
  • mask:可选掩码,用于选择子数组。
  • max:min, compare, inRange, extractImageCOI, mixChannels, split, Mat::重塑

3.2.(cv :: meanStdDev)计算数组元素的平均值和标准偏差

CV_EXPORTS_W void meanStdDev(InputArray src, OutputArray mean, OutputArray stddev,
                             InputArray mask=noArray());
  • src:输入数组应该有1到4个通道,可以将计算结果存在Scalar_ ‘s中
  • mean:平均输出参数:计算的平均值。
  • stddev:输出参数:计算的标准差。
  • mask:可选参数。
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, const char* argv[])
{
    Mat src = imread("../data/test2.jpg", IMREAD_GRAYSCALE);
    if (src.empty()) 
    {
        printf("could not load image...\n");
        return -1;
    }
    namedWindow("input");
    imshow("input", src);
    double minVal, maxVal; 
    Point minLoc, maxLoc; // 先定义
    minMaxLoc(src, &minVal, &maxVal, &minLoc, &maxLoc, Mat()); // 通过引用对变量写入值
    printf("min: %.2f, max: %.2f \n", minVal, maxVal);
    printf("min X: %d, min Y: %d \n", minLoc.x, minLoc.y);
    printf("max X: %d, max Y: %d \n", maxLoc.x, maxLoc.y);
    // 彩色图像 三通道的 均值与方差
    src = imread("../data/test2.jpg");
    namedWindow("RgbImg");
    imshow("RgbImg", src);
    Mat means, stddev; // 均值和方差不是一个值。对彩色图像是三行一列的mat
    meanStdDev(src, means, stddev);
    printf("blue  channel->> mean 均值: %.2f, stddev 方差: %.2f\n", means.at<double>(0, 0), stddev.at<double>(0, 0));
    printf("green channel->> mean 均值: %.2f, stddev 方差: %.2f\n", means.at<double>(1, 0), stddev.at<double>(1, 0));
    printf("red   channel->> mean 均值: %.2f, stddev 方差: %.2f\n", means.at<double>(2, 0), stddev.at<double>(2, 0));
    waitKey(0);
    return 0;
}

执行结果:
在这里插入图片描述

min: 6.00, max: 255.00
min X: 67, min Y: 73
max X: 195, max Y: 37
blue  channel->> mean 均值: 141.64, stddev 方差: 67.47
green channel->> mean 均值: 179.35, stddev 方差: 62.22
red   channel->> mean 均值: 206.31, stddev 方差: 46.79
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

~晓广~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值