基础图像容器Mat
Mat 是一个类,它由两部分的内容组成:矩阵头(包含矩阵尺寸,存储方法,存储地址等信息)和一个指向所有像素值的矩阵,因为OpenCV 是一个图像处理库,包含了大量的图像处理函数,为了解决图像在不同的库中进行传递的问题,Mat 类使用了引用计数机制,拷贝构造函数和赋值运算符只复制信息头和矩阵指针,不复制矩阵
下面的例子只复制矩阵头,不复制图像数据
Mat A,C
A = imread("1.jpg", CV_LOAD_IMAGE_COLOR);
MatB(A);
C = A;
要拷贝图形的像素值,使用下面 copyTo 和 或者 clone 函数
//Mat F = mSrcMat.clone();
//imshow("clone F", F);
Mat M;
mSrcMat.copyTo(M);
imshow("copy_to_M", M);
Mat 类的基本属性如下:
rows 行数 cols 列数 channel 通道数 dims 维数 depth 单行的字节数 size 返回一个Size 类型
cout << "mSrcMat source rows:" << mSrcMat.rows << " cols:" << mSrcMat.cols << " channels: " << mSrcMat.channels() << endl;
cout << " dims: " << mSrcMat.dims << " depth: " << mSrcMat.depth() << " steps(stride): " << mSrcMat.step << " size: " << mSrcMat.size << endl;
图像载入函数 imread
Mat imread( const String& filename, int flags = IMREAD_COLOR );
第一个参数:OpenCV 支持下面类型的图像载入
Windows bitmaps - *.bmp, *.dib
JPEG files - *.jpeg, *.jpg, *.jpe
JPEG 2000 files - *.jp2
Portable Network Graphics - *.png
Portable image format - *.pbm, *.pgm, *.ppm *.pxm, *.pnm
第二个参数 常用的选择如下:
IMREAD_UNCHANGED = -1, //按照图像原样读取,保留Alpha通道(第4通道)
IMREAD_GRAYSCALE = 0, //IMREAD_COLOR 将图像转成单通道灰度图像后读取
IMREAD_COLOR = 1, //将图像转换成3通道BGR彩色图像
IMREAD_ANYDEPTH = 2, //保留原图像的16位、32位深度,不声明该参数则转成8位读取
IMREAD_ANYCOLOR = 4, //以任何可能的颜色读取图像
可以通过 empty 函数判断是否read 正常
图像显示函数 imshow
void imshow(const String& winname, InputArray mat);
第一个参数 表示要显示的窗体标志名称
第二个参数 填写要显示的图像
输出图像到文件 imwrite
bool imwrite( const String& filename, InputArray img, const std::vector<int>& params = std::vector<int>());
第一个参数表示要写入的文件名,输出文件格式用文件名的后缀进行区分
第二个参数是 Mat 类型的图像容器
第三个参数表示为特定格式保存的参数编码
对于 JPEG 文件,用 CV_IMWRITE_JPEG_QUALITY表示图像质量 (0 ~ 100)
对于 PNG 格式图片,使用 CV_IMWRITE_PNG_COMPRESSION (0 ~ 9),较高的值表示较小的压缩尺寸和更长的压缩时间
void basicCvDemo::basicCvImgWrite() {
// PXM BINARY
vector<int> comParams{ CV_IMWRITE_PXM_BINARY, 0 };
{
imwrite("HusKey_output_PXM0.ppm", mSrcMat, comParams);
comParams.clear();
comParams.push_back(CV_IMWRITE_PXM_BINARY);
comParams.push_back(1);
imwrite("HusKey_output_PXM1.ppm", mSrcMat, comParams);
}
//JPEG qualicity
{
comParams.clear();
comParams.push_back(CV_IMWRITE_JPEG_QUALITY);
comParams.push_back(0);
imwrite("HusKey_output_para0.jpg", mSrcMat, comParams);
comParams.clear();
comParams.push_back(CV_IMWRITE_JPEG_QUALITY);
comParams.push_back(30);
imwrite("HusKey_output_para30.jpg", mSrcMat, comParams);
comParams.clear();
comParams.push_back(CV_IMWRITE_JPEG_QUALITY);
comParams.push_back(70);
imwrite("HusKey_output_para70.jpg", mSrcMat, comParams);
}
//PNG 压缩级别
{
comParams.clear();
comParams.push_back(CV_IMWRITE_PNG_COMPRESSION);
comParams.push_back(1);
imwrite("HusKey_output_para1.png", mSrcMat, comParams);
comParams.clear();
comParams.push_back(CV_IMWRITE_PNG_COMPRESSION);
comParams.push_back(5);
imwrite("HusKey_output_para5.png", mSrcMat, comParams);
comParams.clear();
comParams.push_back(CV_IMWRITE_PNG_COMPRESSION);
comParams.push_back(9);
imwrite("HusKey_output_para9.png", mSrcMat, comParams);
}
//bmp
{
imwrite("HusKey_output.bmp", mSrcMat);
}
}
Mat 的构造方法
-
直接使用 Mat 构造函数
Mat demoMat(300, 300, CV_8UC3, Scalar(0, 0, 255)); // BGR
300x300 表示 width 和 height
CV_8UC3 对于CV_[位数][是否带符号]C[通道数] 表示 8位 unsigned 类型,每个像素是三个元素组成的三通道
Scalar(0, 0, 255) 表示单个 pixel 的内容,用于初始化Mat 类型 -
使用 create 函数开辟空间
注意 create 不能对创建的 Mat 类型进行初始化 -
使用 matlab 的形式 zeros ones 初始化
{
Mat demoMat(300, 300, CV_8UC3, Scalar(0, 0, 255)); // BGR
imshow("demoMat", demoMat);
}
{
int sz[3] = { 200,200};
Mat demoMat(2, sz, CV_8UC3, Scalar(0, 0, 255)); // BGR Scalar::all(0)
imshow("demoMat", demoMat);
}
{
Mat demoMat;
demoMat.create(200, 200, CV_8UC(2)); // 不能设置初值 只能开辟空间
}
{
//Mat demoMat = Mat::ones(100, 100, CV_32F);
Mat demoMat = Mat::zeros(100, 100, CV_8UC3);
imshow("demoMat", demoMat);
}
滑动条的创建和使用
滑动条的效果如下如所示:
trackbar.jpg
用滑动条可以快速的调整程序中的参数值,滑动条的创建流程如下:
- 创建一个namedWindow,Trackbar 是依附在 namedWindow 之上的
- createTrackbar 函数创建一个可以调整数值的滑动条,参数中包含一个回调函数,关联的值改变的时候会调用到回调函数
void basicCvDemo::onTrackBarChanged(int pos, void* userdata) {
cout << "pos: " << pos << endl;
double srcAlpha = (double)pos / alphaValueMax;
double srcBeta = 1.0f - srcAlpha;
addWeighted(mSrcAplhaMat, srcAlpha, mDstAplhaMat, srcBeta, 0.0f, mOutputMat);
imshow("alphaBlendWindow", mOutputMat);
}
void basicCvDemo::alphaBlendUsingTarckBar() {
int alphaValueSlider = 50; //初始值
const char* windowName = "alphaBlendWindow";
namedWindow(windowName, 1);
char trackBarName[50] = { 0 };
sprintf_s(trackBarName, "alpha: %d", alphaValueSlider);
createTrackbar(trackBarName, windowName, &alphaValueSlider, alphaValueMax, basicCvDemo::onTrackBarChanged);
//onTrackBarChanged(alphaValueSlider, nullptr); // 每次改变都调用回调函数
}
这里使用了addWeighted 函数,用于实现不同的混合效果
Mat 类中访问像素的几种方式
- 使用at 函数 获取一个3/4 channel 的Vector 类型
- 使用指针模板直接访问像素,但是仅仅适用于 8位无符号整数类型的Mat
- 使用 data 属性获取指向像素区的指针
Mat demoMat(300, 300, CV_8UC4, Scalar(0, 0, 255)); // 4 channels
// using at
{
Vec4b& rgba = demoMat.at<Vec4b>(0, 0);
printf("Pixels at (0,0) : %d %d %d %d\n", rgba[0], rgba[1], rgba[2], rgba[3]);
}
//using ptr 比 at 快,但是仅仅适用于 8位无符号整数类型的Mat
{
int i = 0;
int j = 0;
int pixel_value = demoMat.ptr<uchar>(i)[j];
}
{
unsigned char* ptr = demoMat.data;
printf("Pixels at(0,0) %d %d %d %d \n", ptr[0], ptr[1], ptr[2], ptr[3]);
printf("Pixels at(0,1) %d %d %d %d \n", ptr[4], ptr[5], ptr[6], ptr[7]);
printf("Pixels at(0,1) %d %d %d %d \n", ptr[8], ptr[9], ptr[10], ptr[11]);
}
网友评论