OpenCV開發筆記(四十五):紅胖子8分鐘帶你深入瞭解重映射(圖文並茂+淺顯易懂+程序源碼)

若該文爲原創文章,未經允許不得轉載
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客導航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/105633350
各位讀者,知識無窮而人力有窮,要麼改需求,要麼找專業人士,要麼自己研究

目錄

前言

相關博客

Demo

重映射

概述

X軸旋轉/Y軸旋轉/XY軸旋轉原理示意圖

縮放1/2原理示意圖

傾斜45度示意圖

函數原型

Demo源碼

工程模板:對應版本號v1.40.0


紅胖子(紅模仿)的博文大全:開發技術集合(包含Qt實用技術、樹莓派、三維、OpenCV、OpenGL、ffmpeg、OSG、單片機、軟硬結合等等)持續更新中...(點擊傳送門).

OpenCV開發專欄(點擊傳送門)

 

    OpenCV開發筆記(四十五):紅胖子8分鐘帶你深入瞭解重映射(圖文並茂+淺顯易懂+程序源碼)

 

前言

紅胖子,來也!!!

本篇章講解重映射。

 

相關博客

      圖像檢測中對圖像進行旋轉、鏡像等操作是可以對原尺寸進行操作的,有專門的旋轉、翻轉函數進行處理。

OpenCV開發筆記(八):OpenCV常用操作之計時、縮放、旋轉、鏡像

      該文章中,也同樣實現了部分簡單重映射效果,使用的四個函數:

  • 旋轉函數1:cv::transpose,直接對矩陣進行順時鐘旋轉90°
  • 旋轉函數2:cv::rotate,三個枚舉可以旋轉90°,180°,270°
  • 翻轉函數:cv::flip,xy軸翻轉
  • 縮放函數:cv::resize,縮放

 

Demo

 

重映射

概述

      重映射,按照與原圖一樣大小的尺寸,通過像素下標的序列號的矩陣進行映射得到結果,簡而言之,就是把一幅圖像中某位置的像素放置到另一個圖片指定位置的過程。

X軸旋轉/Y軸旋轉/XY軸旋轉原理示意圖

縮放1/2原理示意圖

傾斜45度示意圖

函數原型

void remap( InputArray src,
            OutputArray dst,
            InputArray map1,
            InputArray map2,
            int interpolation,
            int borderMode = BORDER_CONSTANT,
            const Scalar& borderValue = Scalar());
  • 參數一:InputArray類型的src,一般爲cv::Mat;
  • 參數二:OutputArray類型的dst,目標圖像。它的大小與map1相同,類型與src相同。
  • 參數三:InputArray類型的map1,它有兩種可能的表示對象:表示點(x,y)的第一個映射或者表示CV_16SC2 , CV_32FC1 或CV_32FC2類型的x值。
  • 參數四:InputArray類型的map2,它也有兩種可能的表示對象,而且他是根據map1來確定表示哪種對象。若map1表示點(x,y)時,這個參數不代表任何值,否則,表示CV_16UC1 , CV_32FC1類型的y值(第二個值)。
  • 參數五:int類型的interpolation,使用的插值方法;
  • 參數六:int類型的borderMode,邊界處理方式;
  • 參數七:Scalar類型的borderValue,重映射後,離羣點的背景,需要broderMode設置爲BORDER_CONSTRANT時纔有效。(離羣點:當圖片大小爲400x300,那麼對應的map1和map2範圍爲0~399、0~299,小於0或者大於299的則爲離散點,使用該顏色填充);

 

Demo源碼

void OpenCVManager::testRemap()
{
QString fileName1 =         "E:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/1.jpg";           
    cv::Mat srcMat = cv::imread(fileName1.toStdString());
    cv::Mat dstMat;
    int width = 400;
    int height = 300;

    cv::resize(srcMat, srcMat, cv::Size(width, height));

    cv::String windowName = _windowTitle.toStdString();
    cvui::init(windowName);

    cv::Mat windowMat = cv::Mat(cv::Size(srcMat.cols * 2, srcMat.rows * 4),
                                srcMat.type());

    while(true)
    {
        windowMat = cv::Scalar(0, 0, 0);

        cv::Mat mat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 1),
                                cv::Range(srcMat.cols * 0, srcMat.cols * 1));
        cv::addWeighted(mat, 0.0f, srcMat, 1.0f, 0.0f, mat);

        cv::Mat mapX;
        cv::Mat mapY;
        // 第一種x翻轉
        {
            mapX.create(srcMat.size(), CV_32FC1);
            mapY.create(srcMat.size(), CV_32FC1);
            for(int row = 0; row < srcMat.rows; row++)
            {
                for(int col = 0; col < srcMat.cols; col++)
                {
                    mapX.at<float>(row, col) = static_cast<float>(col);
                    mapY.at<float>(row, col) = static_cast<float>(srcMat.rows - row - 1);
                }
            }
            dstMat.create(srcMat.size(), srcMat.type());
            cv::remap(srcMat,
                      dstMat,
                      mapX,
                      mapY,
                      CV_INTER_LINEAR,
                      cv::BORDER_CONSTANT,
                      cv::Scalar(255, 0, 0));
            mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2),
                            cv::Range(srcMat.cols * 0, srcMat.cols * 1));
            cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
        }
        // 第二種y翻轉
        {
            mapX.create(srcMat.size(), CV_32FC1);
            mapY.create(srcMat.size(), CV_32FC1);
            for(int row = 0; row < srcMat.rows; row++)
            {
                for(int col = 0; col < srcMat.cols; col++)
                {
                    mapX.at<float>(row, col) = static_cast<float>(srcMat.cols - col - 1);
                    mapY.at<float>(row, col) = static_cast<float>(row);
                }
            }
            dstMat.create(srcMat.size(), srcMat.type());
            cv::remap(srcMat,
                      dstMat,
                      mapX,
                      mapY,
                      CV_INTER_LINEAR,
                      cv::BORDER_CONSTANT,
                      cv::Scalar(255, 0, 0));
            mat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 1),
                            cv::Range(srcMat.cols * 1, srcMat.cols * 2));
            cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
        }
        // 第三種x,y翻轉
        {
            mapX.create(srcMat.size(), CV_32FC1);
            mapY.create(srcMat.size(), CV_32FC1);
            for(int row = 0; row < srcMat.rows; row++)
            {
                for(int col = 0; col < srcMat.cols; col++)
                {
                    mapX.at<float>(row, col) = static_cast<float>(srcMat.cols - col - 1);
                    mapY.at<float>(row, col) = static_cast<float>(srcMat.rows - row - 1);
                }
            }
            dstMat.create(srcMat.size(), srcMat.type());
            cv::remap(srcMat,
                      dstMat,
                      mapX,
                      mapY,
                      CV_INTER_LINEAR,
                      cv::BORDER_CONSTANT,
                      cv::Scalar(255, 0, 0));
            mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2),
                            cv::Range(srcMat.cols * 1, srcMat.cols * 2));
            cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
        }
        // 第四種:右半邊拉伸一倍
        {
            mapX.create(srcMat.size(), CV_32FC1);
            mapY.create(srcMat.size(), CV_32FC1);
            for(int row = 0; row < srcMat.rows; row++)
            {
                for(int col = 0; col < srcMat.cols; col++)
                {
                    mapX.at<float>(row, col) = static_cast<float>(col / 2);
                    mapY.at<float>(row, col) = static_cast<float>(row);
                }
            }
            dstMat.create(srcMat.size(), srcMat.type());
            cv::remap(srcMat,
                      dstMat,
                      mapX,
                      mapY,
                      CV_INTER_LINEAR,
                      cv::BORDER_CONSTANT,
                      cv::Scalar(255, 0, 0));
            mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3),
                            cv::Range(srcMat.cols * 0, srcMat.cols * 1));
            cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
        }
        // 第五種,縮小1/2,並顯示在中間,底色爲藍色
        {
            mapX.create(srcMat.size(), CV_32FC1);
            mapY.create(srcMat.size(), CV_32FC1);
            for(int row = 0; row < srcMat.rows; row++)
            {
                for(int col = 0; col < srcMat.cols; col++)
                {
                    if(col < srcMat.cols / 4 || row < srcMat.rows / 4)
                    {
                        mapX.at<float>(row, col) = -1;
                        mapY.at<float>(row, col) = -1;
                    }else if(col >= srcMat.cols / 4 * 3 || row >= srcMat.rows / 4 * 3)
                    {
                        mapX.at<float>(row, col) = -1;
                        mapY.at<float>(row, col) = -1;
                    }else{
                        mapX.at<float>(row, col) = static_cast<float>((col - srcMat.cols / 4) * 2);
                        mapY.at<float>(row, col) = static_cast<float>((row - srcMat.rows / 4) * 2);
                    }
                }
            }
            dstMat.create(srcMat.size(), srcMat.type());
            cv::remap(srcMat,
                      dstMat,
                      mapX,
                      mapY,
                      CV_INTER_LINEAR,
                      cv::BORDER_CONSTANT,
                      cv::Scalar(255, 0, 0));
            mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3),
                            cv::Range(srcMat.cols * 1, srcMat.cols * 2));
            cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
        }
        // 第六種,矩陣旋轉90度(輸出必須和輸入大小一樣,此時可以使用resize縮放至快高對調的比例)
        {
            mapX.create(srcMat.size(), CV_32FC1);
            mapY.create(srcMat.size(), CV_32FC1);
            for(int row = 0; row < srcMat.rows; row++)
            {
                for(int col = 0; col < srcMat.cols; col++)
                {
                    mapX.at<float>(row, col) = static_cast<float>(row);
                    mapY.at<float>(row, col) = static_cast<float>(col);
                }
            }
            dstMat.create(srcMat.size(), srcMat.type());
            cv::remap(srcMat,
                      dstMat,
                      mapX,
                      mapY,
                      CV_INTER_LINEAR,
                      cv::BORDER_CONSTANT,
                      cv::Scalar(255, 0, 0));
            mat = windowMat(cv::Range(srcMat.rows * 3, srcMat.rows * 4),
                            cv::Range(srcMat.cols * 0, srcMat.cols * 1));
            cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
        }
        // 第七種,順時針傾斜45°
        {
            mapX.create(srcMat.size(), CV_32FC1);
            mapY.create(srcMat.size(), CV_32FC1);
            for(int row = 0; row < srcMat.rows; row++)
            {
                for(int col = 0; col < srcMat.cols; col++)
                {
                    mapX.at<float>(row, col) = static_cast<float>((col + (srcMat.cols * 2 - (srcMat.rows - row) - 1)) % srcMat.cols);
                    mapY.at<float>(row, col) = static_cast<float>(row);
                }
            }
            dstMat.create(srcMat.size(), srcMat.type());
            cv::remap(srcMat,
                      dstMat,
                      mapX,
                      mapY,
                      CV_INTER_LINEAR,
                      cv::BORDER_CONSTANT,
                      cv::Scalar(255, 0, 0));
            mat = windowMat(cv::Range(srcMat.rows * 3, srcMat.rows * 4),
                            cv::Range(srcMat.cols * 1, srcMat.cols * 2));
            cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
        }
        // 更新
        cvui::update();
        // 顯示
        cv::imshow(windowName, windowMat);
        // esc鍵退出
        if(cv::waitKey(25) == 27)
        {
            break;
        }
    }
}

 

工程模板:對應版本號v1.40.0

      對應版本號v1.40.0

 

原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客導航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/105633350

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章