opencv 視頻輸出圖像顛倒


問題:

從opengl的渲染環境中獲取影像data數據,然后create一個mat,mat轉化為iplimage,然后保存至視頻文件,打開后發現視頻文件顛倒。

網上搜集原因:

使用opencv顯示圖像時會出現圖像倒立的情況,IplImage的origin屬性有關系。

origin為0表示頂左結構,即圖像的原點是左上角,

如果為1為左下角。

一般從硬盤讀入的圖片或者通過cvCreateImage方法創建的IplImage圖片默認的origin為0,即顯示的時候都是正的。

而由攝像頭或者視頻文件獲取的幀圖像origin為1,此時顯示的時候掃描順序是從下到上,顯示也是正的

opencv顯示的時候是根據origin的值顯示的,如果origin=1,則從下到上顯示,否則反之)。

但是如果你自己創建了一個IplImage格式的圖像img,且從幀圖像中copy或者截取一部分區域進行顯示的時候就會出現倒立情況。

這是因為cvCreateImage方法得到的img的origin是0,而幀圖像的origin為1,

它會將幀圖像的第i行賦值給img的第height-i行,因此就出現了倒立.解決辦法是:在創建之后將origin調整為與幀圖像的origin一致即可。

 

解決辦法:

應該在ilpimage的屬性中修改origin為1。mat到iplimage的轉化時候:只是創建圖像頭,而沒有復制數據。

例: // 假設Mat類型的imgMat圖像數據存在

IplImage pImg= IplImage(imgMat); 

此時修改文件頭,那什么時候復制數據呢?

查看opencv源碼

Mat::operator IplImage() const
{
    CV_Assert( dims <= 2 );
    IplImage img;
    cvInitImageHeader(&img, size(), cvIplDepth(flags), channels());
    cvSetData(&img, data, (int)step[0]);
    return img;
}

  在初始化信息頭函數中:

cvInitImageHeader( IplImage * image, CvSize size, int depth,
                   int channels, int origin, int align )
{
    const char *colorModel, *channelSeq;

    if( !image )
        CV_Error( CV_HeaderIsNull, "null pointer to header" );

    memset( image, 0, sizeof( *image ));
    image->nSize = sizeof( *image );

    icvGetColorModel( channels, &colorModel, &channelSeq );
    strncpy( image->colorModel, colorModel, 4 );
    strncpy( image->channelSeq, channelSeq, 4 );

    if( size.width < 0 || size.height < 0 )
        CV_Error( CV_BadROISize, "Bad input roi" );

    if( (depth != (int)IPL_DEPTH_1U && depth != (int)IPL_DEPTH_8U &&
         depth != (int)IPL_DEPTH_8S && depth != (int)IPL_DEPTH_16U &&
         depth != (int)IPL_DEPTH_16S && depth != (int)IPL_DEPTH_32S &&
         depth != (int)IPL_DEPTH_32F && depth != (int)IPL_DEPTH_64F) ||
         channels < 0 )
        CV_Error( CV_BadDepth, "Unsupported format" );
    if( origin != CV_ORIGIN_BL && origin != CV_ORIGIN_TL )
        CV_Error( CV_BadOrigin, "Bad input origin" );

    if( align != 4 && align != 8 )
        CV_Error( CV_BadAlign, "Bad input align" );

    image->width = size.width;
    image->height = size.height;

    if( image->roi )
    {
        image->roi->coi = 0;
        image->roi->xOffset = image->roi->yOffset = 0;
        image->roi->width = size.width;
        image->roi->height = size.height;
    }

    image->nChannels = MAX( channels, 1 );
    image->depth = depth;
    image->align = align;
    image->widthStep = (((image->width * image->nChannels *
         (image->depth & ~IPL_DEPTH_SIGN) + 7)/8)+ align - 1) & (~(align - 1));
    image->origin = origin;
    image->imageSize = image->widthStep * image->height;

    return image;
}
View Code

可以看到origin的如何傳遞的。到這里找到根本原因了。在mat轉化iplimage時,因為默認的操作函數默認的origin值為零,也就是以左上角為起點,但是glreadpixel是從左下角讀取的。因此出現的翻轉。

解決辦法就是將默認的操作函數,自己重新一遍,添加origin屬性即可。

修改origin屬性后,輸出的視頻仍然存在鏡像錯誤。

利用cvFlip()函數,對每一幀圖像鏡像即可。

 


免責聲明!

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



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