图形图像处理算法(4)---- OpenCV 基础类的使用

2023-03-19  本文已影响0人  特立独行的佩奇

基础图像容器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 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

用滑动条可以快速的调整程序中的参数值,滑动条的创建流程如下:

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 类中访问像素的几种方式

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]);
}
上一篇下一篇

猜你喜欢

热点阅读