2015-10-10 22 views
0

任何人都可以幫助我解決這個問題,如何在不使用內置翻頁功能的情況下翻轉圖像,即使用OpenCV在C++中翻轉(src圖像,目標圖像,1或0)。我對這個軟件很陌生,所以請幫忙。如何在OpenCV中不使用內置函數翻轉來翻轉?

+2

爲什麼你不希望使用內置的功能呢? – DaBrain

+0

剛剛被卡住了,想要做很多努力工作:D – shanu

回答

0

假設你有一個很好的理由不使用OpenCV的flip功能,您可以編寫自定義之一。

對於此示例,我將使用CV_8UC3圖像。最後我會指出如何將其擴展到不同的格式。

讓我們先看看如何翻轉圖像x軸,這對應於cv::flip(src, dst, 1)。給定一個src圖像,dst圖像將具有相同的y座標,並且x座標爲src.cols - 1 - x座標。在實踐中:

void flip_lr(const Mat3b& src, Mat3b& dst) 
{ 
    Mat3b _dst(src.rows, src.cols); 
    for (int r = 0; r < _dst.rows; ++r) { 
     for (int c = 0; c < _dst.cols; ++c) { 
      _dst(r, c) = src(r, src.cols - 1 - c); 
     } 
    } 
    dst = _dst; 
} 

然後,以翻轉左右(對應於cv::flip(src, dst, 0))y軸dst將具有相同的座標x,並ysrc.rows - 1 - y。但是,您可以重複使用上述功能,只需調整dst矩陣,在x軸上應用翻轉,然後轉回。在實踐中:

dst = src.t(); 
flip_lr(dst, dst); 
dst = dst.t(); 

然後翻轉兩個軸,對應於cv::flip(src, dst, -1),你需要簡單的翻蓋上的X和Y軸的結合:

flip_lr(src, dst); 
dst = dst.t(); 
flip_lr(dst, dst); 
dst = dst.t(); 

您可以在自定義的翻蓋包裝這個功能函數採用相同的參數cv::flip

void custom_flip(const Mat3b& src, Mat3b& dst, int code) 
{ 
    if (code > 0) 
    { // Flip x axis 
     flip_lr(src, dst); 
    } 
    else if (code == 0) 
    { 
     // Flip y axis 
     dst = src.t(); 
     flip_lr(dst, dst); 
     dst = dst.t(); 
    } 
    else // code < 0 
    { 
     // Flip x and y axis 
     flip_lr(src, dst); 
     dst = dst.t(); 
     flip_lr(dst, dst); 
     dst = dst.t(); 
    } 
} 

注意,您可以適應這種不同的格式簡單地對矯正的flip_lr功能,並小心調用custom_flip內的相應版本,現在將接受Mat而不是Mat3b

參考全碼:

void flip_lr(const Mat3b& src, Mat3b& dst) 
{ 
    Mat3b _dst(src.rows, src.cols); 
    for (int r = 0; r < _dst.rows; ++r) { 
     for (int c = 0; c < _dst.cols; ++c) { 
      _dst(r, c) = src(r, src.cols - 1 - c); 
     } 
    } 
    dst = _dst; 
} 

void custom_flip(const Mat3b& src, Mat3b& dst, int code) 
{ 
    if (code > 0) 
    { // Flip x axis 
     flip_lr(src, dst); 
    } 
    else if (code == 0) 
    { 
     // Flip y axis 
     dst = src.t(); 
     flip_lr(dst, dst); 
     dst = dst.t(); 
    } 
    else // code < 0 
    { 
     // Flip x and y axis 
     flip_lr(src, dst); 
     dst = dst.t(); 
     flip_lr(dst, dst); 
     dst = dst.t(); 
    } 
} 


int main(void) 
{ 
    Mat3b img = imread("path_to_image"); 

    Mat3b flipped; 
    flip(img, flipped, -1); 

    Mat3b custom; 
    custom_flip(img, custom, -1); 

    imshow("OpenCV flip", flipped); 
    imshow("Custom flip", custom); 
    waitKey(); 

    return 0; 
} 
+0

非常感謝!你的回答幫了我很多。 :) – shanu

+0

@akankshasaini很高興幫助!在SO中,我們通過upvoting表示感謝(並最終將其標記爲答案):D – Miki

+0

@Miki我很想知道您對http://answers.opencv.org/question/74174 – sturkmen

1

OpenCV的翻轉功能使用內部flipHoriz or flipVert函數。

static void 
flipHoriz(const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz) 
{ 
    int i, j, limit = (int)(((size.width + 1)/2)*esz); 
    AutoBuffer<int> _tab(size.width*esz); 
    int* tab = _tab; 

    for(i = 0; i < size.width; i++) 
     for(size_t k = 0; k < esz; k++) 
      tab[i*esz + k] = (int)((size.width - i - 1)*esz + k); 

    for(; size.height--; src += sstep, dst += dstep) 
    { 
     for(i = 0; i < limit; i++) 
     { 
      j = tab[i]; 
      uchar t0 = src[i], t1 = src[j]; 
      dst[i] = t1; dst[j] = t0; 
     } 
    } 
} 

static void 
flipVert(const uchar* src0, size_t sstep, uchar* dst0, size_t dstep, Size size, size_t esz) 
{ 
    const uchar* src1 = src0 + (size.height - 1)*sstep; 
    uchar* dst1 = dst0 + (size.height - 1)*dstep; 
    size.width *= (int)esz; 

    for(int y = 0; y < (size.height + 1)/2; y++, src0 += sstep, src1 -= sstep, 
                dst0 += dstep, dst1 -= dstep) 
    { 
     int i = 0; 
     if(((size_t)src0|(size_t)dst0|(size_t)src1|(size_t)dst1) % sizeof(int) == 0) 
     { 
      for(; i <= size.width - 16; i += 16) 
      { 
       int t0 = ((int*)(src0 + i))[0]; 
       int t1 = ((int*)(src1 + i))[0]; 

       ((int*)(dst0 + i))[0] = t1; 
       ((int*)(dst1 + i))[0] = t0; 

       t0 = ((int*)(src0 + i))[1]; 
       t1 = ((int*)(src1 + i))[1]; 

       ((int*)(dst0 + i))[1] = t1; 
       ((int*)(dst1 + i))[1] = t0; 

       t0 = ((int*)(src0 + i))[2]; 
       t1 = ((int*)(src1 + i))[2]; 

       ((int*)(dst0 + i))[2] = t1; 
       ((int*)(dst1 + i))[2] = t0; 

       t0 = ((int*)(src0 + i))[3]; 
       t1 = ((int*)(src1 + i))[3]; 

       ((int*)(dst0 + i))[3] = t1; 
       ((int*)(dst1 + i))[3] = t0; 
      } 

      for(; i <= size.width - 4; i += 4) 
      { 
       int t0 = ((int*)(src0 + i))[0]; 
       int t1 = ((int*)(src1 + i))[0]; 

       ((int*)(dst0 + i))[0] = t1; 
       ((int*)(dst1 + i))[0] = t0; 
      } 
     } 

     for(; i < size.width; i++) 
     { 
      uchar t0 = src0[i]; 
      uchar t1 = src1[i]; 

      dst0[i] = t1; 
      dst1[i] = t0; 
     } 
    } 
} 

//你可以用一個小的修改使用如下

void myflip(InputArray _src, OutputArray _dst, int flip_mode) 
{ 
CV_Assert(_src.dims() <= 2); 
Size size = _src.size(); 

if (flip_mode < 0) 
{ 
    if (size.width == 1) 
     flip_mode = 0; 
    if (size.height == 1) 
     flip_mode = 1; 
} 

if ((size.width == 1 && flip_mode > 0) || 
    (size.height == 1 && flip_mode == 0) || 
    (size.height == 1 && size.width == 1 && flip_mode < 0)) 
{ 
    return _src.copyTo(_dst); 
} 

Mat src = _src.getMat(); 
int type = src.type(); 
_dst.create(size, type); 
Mat dst = _dst.getMat(); 

size_t esz = CV_ELEM_SIZE(type); 

if(flip_mode <= 0) 
    flipVert(src.ptr(), src.step, dst.ptr(), dst.step, src.size(), esz); 
else 
    flipHoriz(src.ptr(), src.step, dst.ptr(), dst.step, src.size(), esz); 

if(flip_mode < 0) 
    flipHoriz(dst.ptr(), dst.step, dst.ptr(), dst.step, dst.size(), esz); 
}