OpenCV之图像处理(二十三) 像素重映射(cv_remap)

像素重映射:简单点说就是把输入图像中各个像素按照一定的规则映射到另外一张图像的对应位置上去,形成一张新的图像。

remap(
    InputArray src,// 输入图像
    OutputArray dst,// 输出图像
    InputArray  map1,// x 映射表 元素值的数据类型需要是 CV_32FC1/CV_32FC2
    InputArray map2,// y 映射表
    int interpolation,// 选择的插值方法,常见线性插值 INTER_LINEAR,可选择立方等
    int borderMode,// BORDER_CONSTANT
    const Scalar borderValue// borderMode设置为BORDER_CONSTANT时才有用,填充INTER_LINEAR插值时没有计算到的像素点
)

代码

    #include "../common/common.hpp"

    static Mat src, map_x0, map_y0, dst0, map_x1, map_y1, dst1, map_x2, map_y2, dst2, map_x3, map_y3, dst3;
    static void update_map(int);

    void main(int argc, char** argv)
    {
        src = imread(getCVImagesPath("images/test1_3.png"), IMREAD_COLOR);
        imshow("src", src);

        map_x0.create(src.size(), CV_32FC1);//CV_32FC1 其中的1表示单通道,2是双通道,3是三通道,4是四通道
        map_y0.create(src.size(), CV_32FC1);
        map_x1.create(src.size(), CV_32FC1);
        map_y1.create(src.size(), CV_32FC1);
        map_x2.create(src.size(), CV_32FC1);
        map_y2.create(src.size(), CV_32FC1);
        map_x3.create(src.size(), CV_32FC1);
        map_y3.create(src.size(), CV_32FC1);

        update_map(0);
        //图像映射,x对应像素点列的位置,y对应行的位置,INTER_LINEAR表示线性插值
        //假如map_x0第0个位置的值为1,map_y0第0个位置的值为0,那么映射的dst0 (0,0)位置的像素值为src (0,1)位置的像素值
        //只有设置 BORDER_CONSTANT  时,参数 Scalar 才有效,填充插值时未计算到的像素点
        remap(src, dst0, map_x0, map_y0, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 255));
        imshow("dst0", dst0);

        update_map(1);
        remap(src, dst1, map_x1, map_y1, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 255));
        imshow("dst1", dst1);

        update_map(2);
        remap(src, dst2, map_x2, map_y2, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 255));
        imshow("dst2", dst2);

        update_map(3);
        remap(src, dst3, map_x3, map_y3, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 255));
        imshow("dst3", dst3);

        waitKey(0);
    }

    void update_map(int index)
    {
        for (int row = 0; row < src.rows; row++)
        {
            for (int col = 0; col < src.cols; col++)
            {
                switch (index)
                {
                case 0://图像映射,缩小一半,居中显示
                    if (col>=src.cols*0.25 && col<src.cols*0.75 && row>=src.rows*0.25 && row<src.rows*0.75)
                    {
                        map_x0.at<float>(row, col) = 2 * (col - src.cols*0.25);//插值,宽高方向上跳一个像素取一个值
                        map_y0.at<float>(row, col) = 2 * (row - src.rows*0.25);
                    }
                    else
                    {
                        map_x0.at<float>(row, col) = 0;//这里赋值两个0,表示原图(0,0)坐标位置的像素值,而不是表示黑色
                        map_y0.at<float>(row, col) = 0;
                    }
                    break;
                case 1://左右镜像
                    map_x1.at<float>(row, col) = src.cols - col - 1;
                    map_y1.at<float>(row, col) = row;
                    break;
                case 2://上下镜像
                    map_x2.at<float>(row, col) = col;
                    map_y2.at<float>(row, col) = src.rows - row - 1;
                    break;
                case 3://左右上下都镜像
                    map_x3.at<float>(row, col) = src.cols - col - 1;
                    map_y3.at<float>(row, col) = src.rows - row - 1;
                    break;
                }
            }
        }
    }

效果图

这里写图片描述

猜你喜欢

转载自blog.csdn.net/huanghuangjin/article/details/81169821
今日推荐