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

来源:互联网 发布:抠图算法 编辑:程序博客网 时间:2024/06/10 16:19

在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)

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


PS:

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


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



参考:

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











0 0
原创粉丝点击