一、打开图片流程分析

1、读取图片头,进行解码器的寻找

2、根据参数flags,确定图像通道和是否缩放

3、给解码器指定缩放参数和源

4、使用解码器读取图像的头,确保没有问题,失败则输出错误并返回

5、确定图像的宽高,并判断是否超出处理范围。

6、通过解码器获取图像类型

7、根据宽、高、图像类型创建mat

8、通过解码器把图像数据读取到mat中

9、判断是否需要调整大小

二、imread源码查看

源码位置:opencv\modules\imgcodecs\src\loadsave.cpp

入口方法:

/*** Read an image**  This function merely calls the actual implementation above and returns itself.** @param[in] filename File to load* @param[in] flags Flags you wish to set.
*/
Mat imread( const String& filename, int flags )
{//用于应用程序性能分析 参见https://github.com/opencv/opencv/wiki/Profiling-OpenCV-ApplicationsCV_TRACE_FUNCTION();/// create the basic containerMat img;/// load the dataimread_( filename, flags, img );/// optionally rotate the data if EXIF' orientation flag says soif( !img.empty() && (flags & IMREAD_IGNORE_ORIENTATION) == 0 && flags != IMREAD_UNCHANGED ){ApplyExifOrientation(filename, img);}/// return a reference to the datareturn img;
}

主要方法:

/*** Read an image into memory and return the information** @param[in] filename File to load* @param[in] flags Flags* @param[in] hdrtype { LOAD_CVMAT=0,*                      LOAD_IMAGE=1,*                      LOAD_MAT=2*                    }* @param[in] mat Reference to C++ Mat object (If LOAD_MAT)*
*/
static bool
imread_( const String& filename, int flags, Mat& mat )
{/// Search for the relevant decoder to handle the imageryImageDecoder decoder;#ifdef HAVE_GDALif(flags != IMREAD_UNCHANGED && (flags & IMREAD_LOAD_GDAL) == IMREAD_LOAD_GDAL ){decoder = GdalDecoder().newDecoder();}else{
#endifdecoder = findDecoder( filename );
#ifdef HAVE_GDAL}
#endif/// if no decoder was found, return nothing.if( !decoder ){return 0;}int scale_denom = 1;if( flags > IMREAD_LOAD_GDAL ){if( flags & IMREAD_REDUCED_GRAYSCALE_2 )scale_denom = 2;else if( flags & IMREAD_REDUCED_GRAYSCALE_4 )scale_denom = 4;else if( flags & IMREAD_REDUCED_GRAYSCALE_8 )scale_denom = 8;}/// set the scale_denom in the driverdecoder->setScale( scale_denom );/// set the filename in the driverdecoder->setSource( filename );try{// read the header to make sure it succeedsif( !decoder->readHeader() )return 0;}catch (const cv::Exception& e){std::cerr << "imread_('" << filename << "'): can't read header: " << e.what() << std::endl << std::flush;return 0;}catch (...){std::cerr << "imread_('" << filename << "'): can't read header: unknown exception" << std::endl << std::flush;return 0;}// established the required input image sizeSize size = validateInputImageSize(Size(decoder->width(), decoder->height()));// grab the decoded typeint type = decoder->type();if( (flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED ){if( (flags & IMREAD_ANYDEPTH) == 0 )type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));if( (flags & IMREAD_COLOR) != 0 ||((flags & IMREAD_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1) )type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);elsetype = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);}mat.create( size.height, size.width, type );// read the image databool success = false;try{if (decoder->readData(mat))success = true;}catch (const cv::Exception& e){std::cerr << "imread_('" << filename << "'): can't read data: " << e.what() << std::endl << std::flush;}catch (...){std::cerr << "imread_('" << filename << "'): can't read data: unknown exception" << std::endl << std::flush;}if (!success){mat.release();return false;}if( decoder->setScale( scale_denom ) > 1 ) // if decoder is JpegDecoder then decoder->setScale always returns 1{resize( mat, mat, Size( size.width / scale_denom, size.height / scale_denom ), 0, 0, INTER_LINEAR_EXACT);}return true;
}

获取解码器:

下面是png解码器片段,可以看出m_signature就是png图片的标识

PngDecoder::PngDecoder()
{m_signature = "\x89\x50\x4e\x47\xd\xa\x1a\xa";m_color_type = 0;m_png_ptr = 0;m_info_ptr = m_end_info = 0;m_f = 0;m_buf_supported = true;m_buf_pos = 0;m_bit_depth = 0;
}

下面是校验的方法

bool BaseImageDecoder::checkSignature( const String& signature ) const
{size_t len = signatureLength();return signature.size() >= len && memcmp( signature.c_str(), m_signature.c_str(), len ) == 0;
}

获取解码器,从文件头部读取标识,和所有解码器比较

static ImageDecoder findDecoder( const String& filename ) {size_t i, maxlen = 0;/// iterate through list of registered codecsfor( i = 0; i < codecs.decoders.size(); i++ ){size_t len = codecs.decoders[i]->signatureLength();maxlen = std::max(maxlen, len);}/// Open the fileFILE* f= fopen( filename.c_str(), "rb" );/// in the event of a failure, return an empty image decoderif( !f )return ImageDecoder();// read the file signatureString signature(maxlen, ' ');maxlen = fread( (void*)signature.c_str(), 1, maxlen, f );fclose(f);signature = signature.substr(0, maxlen);/// compare signature against all decodersfor( i = 0; i < codecs.decoders.size(); i++ ){if( codecs.decoders[i]->checkSignature(signature) )return codecs.decoders[i]->newDecoder();}/// If no decoder was found, return base typereturn ImageDecoder();
}

 校验图像宽高:这里可以看出宽高以及宽*高都有限制

static const size_t CV_IO_MAX_IMAGE_PARAMS = cv::utils::getConfigurationParameterSizeT("OPENCV_IO_MAX_IMAGE_PARAMS", 50);
static const size_t CV_IO_MAX_IMAGE_WIDTH = utils::getConfigurationParameterSizeT("OPENCV_IO_MAX_IMAGE_WIDTH", 1 << 20);
static const size_t CV_IO_MAX_IMAGE_HEIGHT = utils::getConfigurationParameterSizeT("OPENCV_IO_MAX_IMAGE_HEIGHT", 1 << 20);
static const size_t CV_IO_MAX_IMAGE_PIXELS = utils::getConfigurationParameterSizeT("OPENCV_IO_MAX_IMAGE_PIXELS", 1 << 30);static Size validateInputImageSize(const Size& size)
{CV_Assert(size.width > 0);CV_Assert(static_cast<size_t>(size.width) <= CV_IO_MAX_IMAGE_WIDTH);CV_Assert(size.height > 0);CV_Assert(static_cast<size_t>(size.height) <= CV_IO_MAX_IMAGE_HEIGHT);uint64 pixels = (uint64)size.width * (uint64)size.height;CV_Assert(pixels <= CV_IO_MAX_IMAGE_PIXELS);return size;
}

三、常见几种格式图片文件头标识

png -> 89 50 4e 47 0d 0a 1a 0a

jpg -> FF D8 FF

bmp -> BM  /  42 4D

四、imread函数支持读取的图像格式

  • Windows bitmaps - *.bmp, *.dib (always supported)
  • JPEG files - *.jpeg, *.jpg, *.jpe (see the Note section)
  • JPEG 2000 files - *.jp2 (see the Note section)
  • Portable Network Graphics - *.png (see the Note section)
  • WebP - *.webp (see the Note section)
  • Portable image format - *.pbm, *.pgm, *.ppm *.pxm, *.pnm (always supported)
  • PFM files - *.pfm (see the Note section)
  • Sun rasters - *.sr, *.ras (always supported)
  • TIFF files - *.tiff, *.tif (see the Note section)
  • OpenEXR Image files - *.exr (see the Note section)
  • Radiance HDR - *.hdr, *.pic (always supported)
  • Raster and Vector geospatial data supported by GDAL (see the Note section)

五、flags参数

c++定义 python定义 说明
IMREAD_UNCHANGED Python: cv.IMREAD_UNCHANGED 如果设置,则按原样返回加载的图像(使用Alpha通道,否则会被裁剪)
IMREAD_GRAYSCALE Python: cv.IMREAD_GRAYSCALE 如果设置,则始终将图像转换为单通道灰度图像(编解码器内部转换)。
IMREAD_COLOR Python: cv.IMREAD_COLOR 如果设置,请始终将图像转换为3通道BGR彩色图像。
IMREAD_ANYDEPTH Python: cv.IMREAD_ANYDEPTH 如果设置,则在输入具有相应深度时返回16位/ 32位图像,否则将其转换为8位。
IMREAD_ANYCOLOR Python: cv.IMREAD_ANYCOLOR 如果设置,则以任何可能的颜色格式读取图像。
IMREAD_LOAD_GDAL Python: cv.IMREAD_LOAD_GDAL 如果设置,使用gdal驱动程序加载图像
IMREAD_REDUCED_GRAYSCALE_2 Python: cv.IMREAD_REDUCED_GRAYSCALE_2 如果设置,则始终将图像转换为单通道灰度图像,图像尺寸减小1/2。
IMREAD_REDUCED_COLOR_2 Python: cv.IMREAD_REDUCED_COLOR_2 如果设置,则始终将图像转换为3通道BGR彩色图像,图像尺寸减小1/2。
IMREAD_REDUCED_GRAYSCALE_4 Python: cv.IMREAD_REDUCED_GRAYSCALE_4 如果设置,则始终将图像转换为单通道灰度图像,图像尺寸减小1/4
IMREAD_REDUCED_COLOR_4 Python: cv.IMREAD_REDUCED_COLOR_4 如果设置,则始终将图像转换为3通道BGR彩色图像,图像尺寸减小1/4
IMREAD_REDUCED_GRAYSCALE_8 Python: cv.IMREAD_REDUCED_GRAYSCALE_8 如果设置,则始终将图像转换为单通道灰度图像,图像尺寸减小1/8。
IMREAD_REDUCED_COLOR_8 Python: cv.IMREAD_REDUCED_COLOR_8 如果设置,则始终将图像转换为3通道BGR彩色图像,图像尺寸减小1/8。
IMREAD_IGNORE_ORIENTATION Python: cv.IMREAD_IGNORE_ORIENTATION 如果设置,请不要根据EXIF的方向标志旋转图像。

Opencv学习笔记 - imread源码解读相关推荐

  1. yolov1-v5学习笔记及源码解读

    目录 深度学习网络分类 评价指标 原理 yolov1 yolov2 yolov3 yolov4 yolov5 源码解读(v3为例) 深度学习网络分类 深度学习经典检测方法 通常分为 two-stage ...

  2. 35.FFmpeg学习笔记 - ffplay源码解读3之读文件

    本篇文章看看ffplay是如何读取packet放入队列中的. 一.先看入口函数: int main(int argc, char **argv) {VideoState *is;...av_init_ ...

  3. 34.FFmpeg学习笔记 - ffplay源码解读2之数据结构

    本篇分析一下ffplay的数据结构. (1)VideoState VideoState结构体,正如名字的含义,管理了一些全局的播放状态. typedef struct VideoState {SDL_ ...

  4. sheng的学习笔记-Vector源码分析

    概述 Vector底层也是数组,跟ArrayList很像(先看下ArrayList,再看Vector会很轻松),ArrayList可参考下文,并且由于效率低,已经被淘汰了,大概瞅瞅得了 sheng的学 ...

  5. PixHawk学习笔记 之 源码浅析——mc_pos_control.cpp——task_main

    注意:基于"Firmware-1.6.0rc1" 献上固件源码分享链接:https://pan.baidu.com/s/1kUPocmF 密码:j55a 自己边学边写的,一定有错, ...

  6. 狂神说SpringCloud学习笔记(附带源码和笔记)

    狂神说Spring Cloud Netflix笔记-01(服务注册与发现) 狂神说Spring Cloud Netflix笔记-02(Eureka集群的搭建 ) 狂神说Spring Cloud Net ...

  7. android源码编译 简书,android学习笔记之源码编译

    编译环境 1.需要Ubuntu 64bit,建议Ubuntu14.04 64-bit 2.安装openJDK7 $ sudo apt-get update $ sudo apt-get install ...

  8. dubbo学习笔记 一 源码编译

    前面学习了netty和rocketmq,当然前面的文章还会继续更新,继续往下写 2016 没几天了,我打算写下dubbo 2017 继续深入源码,大家有啥问题 都可以一起来讨论 源码搭建 下载源码 同 ...

  9. as工程放到源码编译_方舟编译器学习笔记2 源码编译

    根据方舟官方文档编译了方舟编译器的源码,在这里简单谈谈其源码的编译过程: 1.操作系统环境: 64位版本的Ubuntu(官方推荐Ubuntu 16.04).我自己本身就有Ubuntu 16.04的虚拟 ...

最新文章

  1. mobaxterm最多10个链接_短袖、纱裙、泳衣…百元左右夏季童装,我回购最多的10个品牌...
  2. Chrome开发,debug的使用方法。
  3. 国际色卡c色号查询_怎幺提取图片中的潘通色卡?图片找色卡
  4. V3S代码整合中遇到的一个奇怪问题
  5. android studio中创建、切换svn分支
  6. 3.Spring高级话题—3.计划任务
  7. 组合数学 —— 组合数取模
  8. 微信内置浏览器不支持 onclick 如何解决?(原因是因为内面中的内容或者标签大部分是动态生成的)...
  9. China Pub 高清书籍6CD 包含的图书目录
  10. 极域电子教室V4窗口化
  11. 哪个大佬有c#三层架构写的餐饮管理系统源代码
  12. 使用超级鹰模拟登录验证码报错的解决办法
  13. win11怎么装回win10系统
  14. 2020年阿里云服务器租用价格表(实时更新)
  15. zend抽象语法树AST流程解析
  16. Kafka09:【案例】Flume集成Kafka
  17. 计算机数值中的乘法除法原理
  18. Mos结电容Cgd、Cgs、Cds与分布参数Ciss、Crss、Coss
  19. 阿里P1到P10,你的能力能拿多少年薪?
  20. win7原版镜像_AMD平台B450主板安装WIN7教程

热门文章

  1. time时间格式转换
  2. unity shader 毛玻璃效果 周围发光效果 Depth.shader
  3. 2022年施工升降机司机(建筑特殊工种)考试试题及在线模拟考试
  4. java 生成的临时pdf文件无法删除
  5. [javaweb企业人力资源管理系统设计与实现(论文+程序设计源码+数据库文件)
  6. 黄吉:如何适配OpenHarmony自有音频框架ADM?
  7. Maluuba人工智能的阅读理解力最佳
  8. Apache配置WebSocket代理
  9. Python3 tkinter 界面布局(转自https://blog.csdn.net/junjun5156/article/details/72510927)
  10. Harbor安装配置