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
- 20170227. EXIF信息的说明(opencv320 ApplyExifOrientation)
- Exif的Orientation信息说明
- 给JPEG添加Exif图片说明信息的简单方法
- 图片文件Exif信息详细说明
- 图片文件Exif信息详细说明
- 获取照片的Exif信息
- 获取图片的exif信息
- 读取照片的Exif信息
- jpeg图片的exif信息
- 读取JPG图片的Exif属性(一) - Exif信息简介
- 用C#读取数码相片的EXIF信息(一)
- 用C#读取数码相片的EXIF信息(一)
- 读取JPG图片的Exif属性(三) - Exif属性读取GPS信息代码(C/C++实现)
- 用C#读取图片的EXIF信息
- 获取图片的EXIF信息如此困难?
- Java 读取 JPEG 文件的 exif 信息
- flex获取图片的EXIF信息
- C# 获取图片的EXIF 信息
- curl、fopen和file_get_contents区别
- mysql 1115-unknown character set XXXX
- ios学习笔记之-点击一个按钮弹出拨打电话提示框
- webrtcglossary.com
- properties文件、getResouce()方法、getResourceAsStream()方法
- 20170227. EXIF信息的说明(opencv320 ApplyExifOrientation)
- android禁止EditText输入emoji表情图片
- ViewPager+FragmentPagerAdapter刷新
- 原码,反码和补码
- android blogs
- RN源码分析
- 二维图形旋转公式的推导
- windows下部署免费ssl证书(letsencrypt)
- Spring面试,IoC和AOP的理解