20170227. EXIF信息的说明(opencv320 ApplyExifOrientation)

在opencv3.2.0中,对imread函数做了修改

Mat imread( const String& filename, int flags )
{
    /// create the basic container
    Mat img;

    /// load the data
    imread_( filename, flags, LOAD_MAT, &img );


    /// optionally rotate the data if EXIF' orientation flag says so
    if( (flags & IMREAD_IGNORE_ORIENTATION) == 0 && flags != IMREAD_UNCHANGED )
    {
        ApplyExifOrientation(filename, img);
    }

    /// return a reference to the data
    return img;
}

这是320源码中 loadsave.cpp的内容。

可以看到,对于 imread 的 flag 的处理中,增加了一个 ApplyExifOrientation 函数,该函数源码如下:

static void ApplyExifOrientation(const String& filename, Mat& img)
{
    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格式


百度一下大概知,这里简单总结一下:


JPEG格式(Joint Photographic Experts Group(联合图像专家小组)的缩写)的图像(注意,*.jpg和*.jpeg是这种格式图像的拓展名,两个基本没差),在内容中存储有一段设备和图像的基本信息。EXIF也是一种格式,指按照一定的规则书写这些信息(包括相机、曝光、光圈、等等)。我们要说明的是其中的“方向”


1. 先定义一下基本的方向:就是图像本身是怎么存储的。(其实不是废话,继续往下看)

2. 然后,EXIF信息中包含了一个方向值,其决定了将图读到内存的时候,要不要翻转(flip)或旋转(transpose)图像。

    注意,图像在硬盘里的数据存储顺序和在内存中不一定一样。

    这个值和对应的方向,如图所示。top, bottom , left side , right side 表示图像原来的位置,0 th row 和 0 th colum 分别表示在内存里首行和首列是top, bottom , left side , right side中的谁。所以,这就是对应关系了。图像会被按照这个规则,在 ApplyExifOrientation 函数中被翻转(flip)或旋转(transpose)

20170227. EXIF信息的说明(opencv320 ApplyExifOrientation)_第1张图片

3. 看看代码,就清楚了。


PS:

EXIF信息,不是所有图像都含有的。有一些相机支持存储此类信息。读图的时候,最好使用CV_LOAD_IMAGE_UNCHANGED,假如你不希望图像被旋转的话。遇到图像莫名其妙的被旋转,也可能就是这个问题。imread 函数默认的是 IMREAD_COLOR 。


EXIT的信息,可以通过代码(openexif)或者软件(JPEG Lossless Rotator)查看



参考:

http://sylvana.net/jpegcrop/exif_orientation.html












你可能感兴趣的:(OpenCV)