opencv圖像重映射


通過映射改變圖像,實現翻轉放大和縮小

API

cv::remap  (   
    InputArray    src,
    OutputArray    dst,
    InputArray    map1,
    InputArray    map2,
    int        interpolation,
    int        borderMode = BORDER_CONSTANT,
    const Scalar    borderValue = Scalar()
    )

第一個參數,InputArray類型的src,輸入圖像,即源圖像,填Mat類的對象即可,且需為單通道8位或者浮點型圖像。

第二個參數,OutputArray類型的dst,函數調用后的運算結果存在這里,即這個參數用於存放函數調用后的輸出結果,需和源圖片有一樣的尺寸和類型

第三個參數,InputArray類型的map1,它有兩種可能的表示對象。表示點(x,y)的第一個映射。表示CV_16SC2 , CV_32FC1 或CV_32FC2類型的X值。

第四個參數,InputArray類型的map2,同樣,它也有兩種可能的表示對象,而且他是根據map1來確定表示那種對象。若map1表示點(x,y)時。這個參數不代表任何值。表示CV_16UC1 , CV_32FC1類型的Y值(第二個值)。

第五個參數,int類型的interpolation,插值方式,之前的resize( )函數中有講到,需要注意,resize( )函數中提到的INTER_AREA插值方式在這里是不支持的,所以可選的插值方式如下:INTER_NEAREST - 最近鄰插值INTER_LINEAR – 雙線性插值(默認值)INTER_CUBIC – 雙三次樣條插值(逾4×4像素鄰域內的雙三次插值)INTER_LANCZOS4 -Lanczos插值(逾8×8像素鄰域的Lanczos插值)

第六個參數,int類型的borderMode,邊界模式,有默認值BORDER_CONSTANT,表示目標圖像中“離群點(outliers)”的像素值不會被此函數修改。

第七個參數,const Scalar&類型的borderValue,當有常數邊界時使用的值,其有默認值Scalar( ),即默認值為0。

 

demo,通過按鍵1234實現水平翻轉,垂直翻轉,水平垂直翻轉和縮小

#include"pch.h"
#include<iostream>
#include<opencv2\opencv.hpp>

using namespace std;
using namespace cv;

#define INPUT_TITLE "input image"
#define OUTPUT_TITLE "remap image"

Mat img, src;//img 輸入圖像 ; src 最終輸出的圖像
Mat map_x, map_y;
int index = 0;
void updata_map();

int main() {

    img = imread("b.jpg");
    if (!img.data)
    {
        cout << "ERROR : could not load image.";
        return -1;
    }
    namedWindow(INPUT_TITLE, CV_WINDOW_AUTOSIZE);
    namedWindow(OUTPUT_TITLE, CV_WINDOW_AUTOSIZE);

    imshow(INPUT_TITLE, img);

    //建立映射表
    map_x.create(img.size(), CV_32FC1);
    map_y.create(img.size(), CV_32FC1);

    int c = 0;
    while (true)
    {
        c = waitKey(500);
        index = c % 4;
        if ((char)c == 27)
        {
            break;
        }
        updata_map();
        remap(img, src, map_x, map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 255));
        imshow(OUTPUT_TITLE, src);
    }


    return 0;
}

void updata_map() {
    for (int row = 0; row < img.rows; row++)
    {
        for (int col = 0; col < img.cols; col++)
        {
            switch (index)
            {
                //index = 0 ,圖像的行跟列為為原來的1/2。
                //index = 1,為左右翻轉(列變換,行不變)
                //index = 2,為上下翻轉(行變換,列不變)
                //index = 3,為中心旋轉

            case 0:
                if (col > (img.cols*0.25) && col<(img.cols*0.75) && row>(img.rows*0.25) && row < (img.rows*0.75)) {
                    map_x.at<float>(row, col) = 2 * (col - (img.cols*0.25));
                    map_y.at<float>(row, col) = 2 * (row - (img.rows*0.25) - 0.25);
                }
                else
                {
                    map_x.at<float>(row, col) = 0;
                    map_y.at<float>(row, col) = 0;
                }
                break;
            case 1:
                map_x.at<float>(row, col) = (img.cols - col - 1);
                map_y.at<float>(row, col) = row;
                break;
            case 2:
                map_x.at<float>(row, col) = col;
                map_y.at<float>(row, col) = (img.rows - row - 1);
                break;
            case 3:
                map_x.at<float>(row, col) = (img.cols - col - 1);
                map_y.at<float>(row, col) = (img.rows - row - 1);
                break;

            default:
                break;
            }
        }
    }
}

其中縮小的mapx和mapy仍沒有搞清楚,我覺得大圖映射到小圖應該是: 大圖的像素點/2+0.25*大圖尺寸,和demo的公式正好是反過來的

 

 1

 

 2

 

 3

 

 4

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM