在用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 <opencv2/opencv.hpp>
#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