2015-10-05 89 views
3

我有RGB圖像,例如,尺寸2×2的如下:複製OpenCV中的像素值

[ 0, 14, 255, 75, 156, 255; 
    45, 255, 234, 236, 141, 255] 

我想複製每個像素(所有RGB通道的)2×2次,並獲得看起來像的圖像:

[ 0, 14, 255, 0, 14, 255, 75, 156, 255, 75, 156, 255; 
    0, 14, 255, 0, 14, 255, 75, 156, 255, 75, 156, 255; 
    45, 255, 234, 45, 255, 234, 236, 141, 255, 236, 141, 255; 
    45, 255, 234, 45, 255, 234, 236, 141, 255, 236, 141, 255 ] 

在Matlab中或Python,我會只需使用kron函數即可完成此操作,但我無法知道如何在OpenCV C++中輕鬆完成此操作。請注意,這是一個微不足道的例子,我實際上想要通過16x16來複制每個像素,並且在更大的圖像上進行,而不是當然是2x2。

+0

我想'CV :: resize'與插補'INTER_NEAREST'會做的伎倆。發現一個[類似的問題](http://stackoverflow.com/questions/19342543/enlarge-image-pixels-with-opencv),確認調整大小的想法。雖然,我還沒有嘗試/使用過這種插值。 – wendelbsilva

+0

你可以請張貼你將如何做到這一點在Matlab? – Miki

+1

Hi @Miki,你是什麼意思的Matlab?我雖然你的問題是如何使用OpenCV和C++做到這一點。無論如何,我只是嘗試在這裏,它的工作原理。我使用了命令'cv :: resize(m,放大,cv :: Size(m.rows * 20,m.cols * 20),20,20,cv :: INTER_NEAREST);'調整20x的大小(所以我可以查看並驗證結果)。 – wendelbsilva

回答

6

您可以使用resize與近鄰插值INTER_NEAREST

代碼:

Mat mInput(2, 2, CV_8UC3),mOutput(4, 4, CV_8UC3); 

mInput.at<Vec3b>(0,0)= Vec3b(0,14,255); 
mInput.at<Vec3b>(0,1)= Vec3b(75,156,255); 
mInput.at<Vec3b>(1,0)= Vec3b(45,255,234); 
mInput.at<Vec3b>(1,1)= Vec3b(236,141,255); 

cout<<mInput<<"\n"; 

resize(mInput,mOutput,Size(4,4),0,0,INTER_NEAREST); 

cout<<mOutput<<"\n";;  

輸出

[ 0, 14, 255, 75, 156, 255; 
    45, 255, 234, 236, 141, 255] 
[ 0, 14, 255, 0, 14, 255, 75, 156, 255, 75, 156, 255; 
    0, 14, 255, 0, 14, 255, 75, 156, 255, 75, 156, 255; 
    45, 255, 234, 45, 255, 234, 236, 141, 255, 236, 141, 255; 
    45, 255, 234, 45, 255, 234, 236, 141, 255, 236, 141, 255] 
Press any key to continue . . . 

感謝@wendelbsilva在評論指出這一點。

+0

我測試了更大的圖像和更大的尺寸。只要您在'resize'中提供正確的大小,此方法就可以正常工作。你總是學到新的東西:D好電話 – Miki

+0

好極了!我不知道「調整大小」有這樣的選擇。 – chronosynclastic

0

你可以將kron函數包裝起來,像在Matlab和Python中一樣。請注意,Kronecker產品是在單通道矩陣上定義的,因此您需要拆分平面BGR矩陣,應用kron,然後合併回去。

這下面的代碼即可產生精確的輸出:

#include <opencv2\opencv.hpp> 
#include <iostream> 
using namespace std; 
using namespace cv; 

Mat kron(const Mat A, const Mat B) 
{ 
    CV_Assert(A.channels() == 1 && B.channels() == 1); 

    Mat1d Ad, Bd; 
    A.convertTo(Ad, CV_64F); 
    B.convertTo(Bd, CV_64F); 

    Mat1d Kd(Ad.rows * Bd.rows, Ad.cols * Bd.cols, 0.0); 

    for (int ra = 0; ra < Ad.rows; ++ra) 
    { 
     for (int ca = 0; ca < Ad.cols; ++ca) 
     { 
      Kd(Range(ra*Bd.rows, (ra + 1)*Bd.rows), Range(ca*Bd.cols, (ca + 1)*Bd.cols)) = Bd.mul(Ad(ra, ca)); 
     } 
    } 
    Mat K; 
    Kd.convertTo(K, A.type()); 
    return K; 

} 

int main() 
{ 
    Mat3d A(2,2); 
    A(0, 0) = Vec3d(0, 14, 255); 
    A(0, 1) = Vec3d(75, 156, 255); 
    A(1, 0) = Vec3d(45, 255, 234); 
    A(1, 1) = Vec3d(236, 141, 255); 

    cout << "A:" << endl; 
    cout << A << endl; 

    Mat1d B = Mat1d::ones(2,2); 

    cout << "B:" << endl; 
    cout << B << endl; 

    vector<Mat> planes; 
    split(A, planes); 

    for (int i = 0; i < 3; ++i) 
    { 
     planes[i] = kron(planes[i], B); 
    } 

    Mat K; 
    merge(planes, K); 

    cout << "K:" << endl; 
    cout << K << endl; 


    return 0; 
}