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