Opencv学习笔记 - imread源码解读
一、打开图片流程分析
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源码解读相关推荐
- yolov1-v5学习笔记及源码解读
目录 深度学习网络分类 评价指标 原理 yolov1 yolov2 yolov3 yolov4 yolov5 源码解读(v3为例) 深度学习网络分类 深度学习经典检测方法 通常分为 two-stage ...
- 35.FFmpeg学习笔记 - ffplay源码解读3之读文件
本篇文章看看ffplay是如何读取packet放入队列中的. 一.先看入口函数: int main(int argc, char **argv) {VideoState *is;...av_init_ ...
- 34.FFmpeg学习笔记 - ffplay源码解读2之数据结构
本篇分析一下ffplay的数据结构. (1)VideoState VideoState结构体,正如名字的含义,管理了一些全局的播放状态. typedef struct VideoState {SDL_ ...
- sheng的学习笔记-Vector源码分析
概述 Vector底层也是数组,跟ArrayList很像(先看下ArrayList,再看Vector会很轻松),ArrayList可参考下文,并且由于效率低,已经被淘汰了,大概瞅瞅得了 sheng的学 ...
- PixHawk学习笔记 之 源码浅析——mc_pos_control.cpp——task_main
注意:基于"Firmware-1.6.0rc1" 献上固件源码分享链接:https://pan.baidu.com/s/1kUPocmF 密码:j55a 自己边学边写的,一定有错, ...
- 狂神说SpringCloud学习笔记(附带源码和笔记)
狂神说Spring Cloud Netflix笔记-01(服务注册与发现) 狂神说Spring Cloud Netflix笔记-02(Eureka集群的搭建 ) 狂神说Spring Cloud Net ...
- android源码编译 简书,android学习笔记之源码编译
编译环境 1.需要Ubuntu 64bit,建议Ubuntu14.04 64-bit 2.安装openJDK7 $ sudo apt-get update $ sudo apt-get install ...
- dubbo学习笔记 一 源码编译
前面学习了netty和rocketmq,当然前面的文章还会继续更新,继续往下写 2016 没几天了,我打算写下dubbo 2017 继续深入源码,大家有啥问题 都可以一起来讨论 源码搭建 下载源码 同 ...
- as工程放到源码编译_方舟编译器学习笔记2 源码编译
根据方舟官方文档编译了方舟编译器的源码,在这里简单谈谈其源码的编译过程: 1.操作系统环境: 64位版本的Ubuntu(官方推荐Ubuntu 16.04).我自己本身就有Ubuntu 16.04的虚拟 ...
最新文章
- mobaxterm最多10个链接_短袖、纱裙、泳衣…百元左右夏季童装,我回购最多的10个品牌...
- Chrome开发,debug的使用方法。
- 国际色卡c色号查询_怎幺提取图片中的潘通色卡?图片找色卡
- V3S代码整合中遇到的一个奇怪问题
- android studio中创建、切换svn分支
- 3.Spring高级话题—3.计划任务
- 组合数学 —— 组合数取模
- 微信内置浏览器不支持 onclick 如何解决?(原因是因为内面中的内容或者标签大部分是动态生成的)...
- China Pub 高清书籍6CD 包含的图书目录
- 极域电子教室V4窗口化
- 哪个大佬有c#三层架构写的餐饮管理系统源代码
- 使用超级鹰模拟登录验证码报错的解决办法
- win11怎么装回win10系统
- 2020年阿里云服务器租用价格表(实时更新)
- zend抽象语法树AST流程解析
- Kafka09:【案例】Flume集成Kafka
- 计算机数值中的乘法除法原理
- Mos结电容Cgd、Cgs、Cds与分布参数Ciss、Crss、Coss
- 阿里P1到P10,你的能力能拿多少年薪?
- win7原版镜像_AMD平台B450主板安装WIN7教程
热门文章
- time时间格式转换
- unity shader 毛玻璃效果 周围发光效果 Depth.shader
- 2022年施工升降机司机(建筑特殊工种)考试试题及在线模拟考试
- java 生成的临时pdf文件无法删除
- [javaweb企业人力资源管理系统设计与实现(论文+程序设计源码+数据库文件)
- 黄吉:如何适配OpenHarmony自有音频框架ADM?
- Maluuba人工智能的阅读理解力最佳
- Apache配置WebSocket代理
- Python3 tkinter 界面布局(转自https://blog.csdn.net/junjun5156/article/details/72510927)
- Harbor安装配置