• 山东大学数字图像处理实验(一)


    1.实验一

    1.1.实验过程中遇到和解决的问题

    题目:加载并显示图像

    #include 
    #include 
    #include 
    using namespace std;
    using namespace cv;
    
    int main()
    {
        Mat image = imread("D:\\cLion\\project\\image\\2.jpg");
        imshow("First image", image);
        waitKey(0);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • imread函数原型为 imread(const string& filename, int flags=1)
      • 这里的 filename 需要的是图像的路径。该函数从文件中加载图像并返回一个矩阵,如果图像不能被读取,则返回一个空的矩阵
      • 这里介绍一下不同 flag 的效果
        • flag=-1:8位深度,原通道
        • flag=0:8位深度,单通道(读取出来是灰度图)
        • flag=1:8位深度,3通道(RGB)
        • flag=2:原深度,单通道
        • flag=3:原深度,3通道
        • flag=4:8位深度,3通道
    • waitkey()控制这 imshow(n) 的窗口持续时间,单位是 ms,图像显示窗口将在 n ms 后关闭
      • waitkey()waitkey(0) 都表示无限等待
      • 当等待时间内无任何操作时等待结束后返回-1。
      • 当等待时间内有输入字符时,则返回输入字符的ASCII码对应的十进制值
      • 如果waitKey处于一个循环中,里面的参数将显示视频读取的帧(显示视频时使用)

    1.2.结果

    在这里插入图片描述

    2.实验二

    题目:实现一个读取图像任意通道的函数

    2.1.实验过程中遇到和解决的问题

    #include
    #include
    #include
    #include
    using namespace std;
    using namespace cv;
    
    void getChannel(const uchar* input, int width, int height, int inStep, int inChannels, uchar* output, int outStep, int channelToGet){
        for (int y = 0; y < height; ++y, input += inStep, output += outStep){
            const uchar* px = input; // 二维数组中每个一维数组的起始地址
            for (int x = 0; x < width; ++x, px += inChannels)
                output[x] = px[channelToGet]; //一维数组访问元素
        }
    }
    
    
    int main()
    {
        Mat image = imread("D:\\cLion\\project\\image\\2.jpg");
        Mat output_image(image.size(), CV_8UC1); // 将输出图像设置为单通道
    
        getChannel(image.data, image.cols, image.rows, image.step, image.channels(), output_image.data, output_image.step, 2);
        imshow("output", output_image);
        waitKey(0);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 这里需要注意的是,图像的 data 部分是一个二维数组,像通常的二维数组一样访问就好了
    • 将输出图像设置为单通道图像操作起来更方便
    • 每次都取输入和输出二维数组的起始地址(就是处理完一行后,将首地址加上 step
      • 每次都处理一行,按照访问一维数组的方式来进行赋值即可

    2.2.结果

    B通道:

    在这里插入图片描述

    G通道:

    在这里插入图片描述

    R通道:

    在这里插入图片描述

    3.实验三

    题目:现有一张4通道透明图像 a.png

    • 从其中提取出 alpha 通道并显示
    • alpha 混合,为透明图像替换一张新的背景

    3.1.实验过程中遇到和解决的问题

    #include 
    #include 
    #include 
    using namespace std;
    using namespace cv;
    
    int main()
    {
        Mat imageA = imread("D:\\cLion\\project\\alpha.png", IMREAD_UNCHANGED); // 前景
        Mat imageB = imread("D:\\cLion\\project\\sdu01.png"); // 背景
        vector mask_channels;
        float alpha = 1.0;
        // 分离通道
        split(imageA, mask_channels); // 分离出 RGBA 分别作为一个图像
        // 取出 alpha 通道
        Mat mask = mask_channels[3];
        imshow("alpha image", mask);
        waitKey(1000); // 看个三秒
    
        Mat mixImage(imageB.size(), CV_8UC3);
        for (int i = 0; i < imageB.rows; i++)
            for (int j = 0; j < imageB.cols; j++) {
                if (i < imageA.rows && j < imageA.cols && mask.at(i, j))
                    for(int k = 0; k < 3; k++) mixImage.at(i, j)[k] = saturate_cast(alpha * float(imageA.at(i, j)[k]) + (1 - alpha) * float(imageB.at(i, j)[k]));
    
                else mixImage.at(i, j) = imageB.at(i, j);
        }
    
        imshow("mixed image", mixImage);
        waitKey(0);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 首先读进四通道图像
      • imread()函数后面的参数是 -1 或者 IMREAD_UNCHANGED 时代表读入原通道,而 png 图像本身就是具有 alpha 通道的,所以加了这两个参数(这俩都行),就能够读入四通道图像(注意:jpg 图像是没有第四个通道的),这张作为前景图
      • 背景图是否读入四通道个人认为意义不大,因为合成时是将前景图嵌入到背景图中,所以三通道就可以了。
      • split 函数的功能是进行通道分离(其实实验二的通道分离就是这个函数)
      • 设置一个 alpha 合成参数,当然也可以根据图像的 alpha 通道值来确定
      • 遍历背景图,如果当前位置前景图存在,则将前景图与背景图融合
        • 注意,四通道图像访问要使用 Vec4b,三通道图像使用的是 Vec3b
        • saturate_cast 函数的功能是防止数据溢出(大于255时设置为255,小于0时设置为0)
        • 没有前景图的地方直接等于背景图像素就好了

    3.2.结果

    • alpha image:

    在这里插入图片描述

    • mixed image:

    在这里插入图片描述

  • 相关阅读:
    jenkins系列-07.轻易级jpom安装
    程序员的工作内容
    Excel 数据透视表教程大全之 05 数据透视表绘制各种二维排列的数据,实现双向枢轴(教程含数据)
    c++ stl的迭代器部分功能可以这样实现
    Linux下解压tar.xz文件的命令
    Verdaccio部署及基础使用
    【NODE.JS】多进程架构(二)—— 句柄传递
    el-table进阶(每条数据分行或合并)
    块设备 I/O 请求送达到外部设备
    kinetic: 编译navgation包遇到的问题
  • 原文地址:https://blog.csdn.net/qq_52852138/article/details/126918579