在opencv2.4.x版本中处理图像EXIF orientation不统一的问题

在用opencv的imread函数读取手机拍的照片时会出现翻转的情况,即用opencv中的imshow看到的图像和手机上看到的图像的宽高是相反的。(当然,读取电脑上的照片时也可能会出现这个问题)
出现这个问题的原因是opencv中的imread函数读取图像时没有对图像exif中的orientation信息进行解析。而通常的看图工具打开图像时都会根据orientation对图像进行相应的翻转以便我们看到的图像是正常的。
通过查找发现在opencv的源码github中,有人解决了读取orientation的问题,并且在opencv源码中进行了提交。另外,在opencv3.2中也对该问题进行了相关的支持。

为了解决该问题,我从源码中抽取了exif.hpp和exif.cpp两个相关文件,并通过如下函数成功解决了根据orientation对图像进行翻转。

void ReadWithExifOrientation(const String& filename, Mat& img)
{
    img = imread(filename);
    int orientation = IMAGE_ORIENTATION_TL;

    if (filename.size() > 0)
    {
        ExifReader reader( filename );
        if( reader.parse() )
        {
            ExifEntry_t entry = reader.getTag( ORIENTATION );
            if (entry.tag != INVALID_TAG)
            {
                orientation = entry.field_u16; //orientation is unsigned short, so check field_u16
            }
        }
    }

    switch( orientation )
    {
        case    IMAGE_ORIENTATION_TL: //0th row == visual top, 0th column == visual left-hand side
            //do nothing, the image already has proper orientation
            break;
        case    IMAGE_ORIENTATION_TR: //0th row == visual top, 0th column == visual right-hand side
            flip(img, img, 1); //flip horizontally
            break;
        case    IMAGE_ORIENTATION_BR: //0th row == visual bottom, 0th column == visual right-hand side
            flip(img, img, -1);//flip both horizontally and vertically
            break;
        case    IMAGE_ORIENTATION_BL: //0th row == visual bottom, 0th column == visual left-hand side
            flip(img, img, 0); //flip vertically
            break;
        case    IMAGE_ORIENTATION_LT: //0th row == visual left-hand side, 0th column == visual top
            transpose(img, img);
            break;
        case    IMAGE_ORIENTATION_RT: //0th row == visual right-hand side, 0th column == visual top
            transpose(img, img);
            flip(img, img, 1); //flip horizontally
            break;
        case    IMAGE_ORIENTATION_RB: //0th row == visual right-hand side, 0th column == visual bottom
            transpose(img, img);
            flip(img, img, -1); //flip both horizontally and vertically
            break;
        case    IMAGE_ORIENTATION_LB: //0th row == visual left-hand side, 0th column == visual bottom
            transpose(img, img);
            flip(img, img, 0); //flip vertically
            break;
        default:
            //by default the image read has normal (JPEG_ORIENTATION_TL) orientation
            break;
    }
}

exif.hpp和exif.cpp下载地址:http://download.csdn.net/detail/computerme/9884696
使用姿势如下:

#include 
#include "exif.hpp"

int  main(int argc,char *argv[])
{
    char* testimage = "/Users/Downloads/IMG_4198.JPG";
    Mat img; 
    ReadWithExifOrientation(testimage, img);  //new image read function

    return 1;
}

Reference:
https://github.com/opencv/opencv/pull/5538/commits/0a306f88047586356548335f5e8c9697ce43b8fc
https://my.oschina.net/shf/blog/876489
https://fossies.org/dox/opencv-3.2.0/exif_8cpp_source.html
http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html

你可能感兴趣的:(opencv,图像处理)