opencv Mat To Heif
高效率图像文件格式(英语:High Efficiency Image File Format, HEIF;也称高效图像文件格式)是一个用于单张图像或图像序列的文件格式。它由运动图像专家组(MPEG)开发,并在MPEG-H Part 12(ISO/IEC 23008-12)中定义。
HEIF规范也定义了高效率视频编码(HEVC)编码的内嵌图像和HEVC编码的图像序列的存储方式,其中以受约束的方式应用帧间预测。
HEIF文件与ISO基本媒体文件格式(ISOBMFF,ISO/IEC 14496-12)兼容,并且还可以包括其他媒体流,例如定时的文本和音频。
环境配置:
相关资源:https://github.com/strukturag/libheif
Windows(最简单、快捷方式,自行编译容易出错)
You can build and install libheif using the vcpkg dependency manager:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.bat
./vcpkg integrate install
./vcpkg install libheif
Linux/macOS(或参考上述相关资源链接)
1. Install dependencies with Homebrew
brew install cmake make pkg-config x265 libde265 libjpeg libtool
2. Configure and build project (–preset argument needs CMake >= 3.21):
mkdir buildcd buildcmake --preset=release .../configuremake
功能:cv::Mat 转 HEIF文件, HEIF文件转cv::Mat
```cpp
#include <libheif/heif.h>
#include <opencv2/opencv.hpp>
#include <iostream>bool RGBMatToHeif(cv::Mat& mat, const char* filename)
{if (mat.empty() || mat.type() != CV_8UC3){std::cerr << "Invalid Mat format. Expected 8UC3." << std::endl;return false;}struct heif_image* image;struct heif_context* ctx = heif_context_alloc();struct heif_error err;int width = mat.cols;int height = mat.rows;// 创建HEIF图像err = heif_image_create(width, height, heif_colorspace_RGB, heif_chroma_interleaved_RGB, &image);if (err.code != heif_error_Ok){std::cerr << "Error adding plane to HEIF image:" << err.message << std::endl;heif_image_release(image);heif_context_free(ctx);return false;}// 添加一个用于交错 RGB 通道的图像平面err = heif_image_add_plane(image, heif_channel_interleaved, width, height, 8);if (err.code != heif_error_Ok) {std::cerr << "Error adding plane to HEIF image: " << err.message << std::endl;heif_image_release(image);heif_context_free(ctx);return false;}// 获取指向HEIF图像数据的指针int stride;uint8_t* p = heif_image_get_plane(image, heif_channel_interleaved, &stride);// 将 cv::Mat 数据复制到 HEIF 图像中for (int y = 0; y < height; y++) {memcpy(p + y * stride, mat.ptr(y), width * 3); // 每行的像素数据都是 width * 3 个字节}//for (int y = 0; y < height; y++) {// // 使用 size_t 来安全地计算偏移量 // size_t rowOffset = static_cast<size_t>(y) * stride;// // 将偏移量转换为 char* 类型的指针偏移 // char* rowPtr = reinterpret_cast<char*>(p) + rowOffset;// // 使用 memcpy 复制数据 // memcpy(rowPtr, mat.ptr<uchar>(y), width * 3); // 注意:这里假设 mat.ptr 返回 uchar* // // 注意:如果 mat.ptr 实际上返回的是其他类型的指针(如 RGB 像素的 struct 或类), // // 你可能需要调整 memcpy 的第三个参数来匹配实际的字节大小。 //}创建并初始化heif_encoding_options结构体//struct heif_encoding_options encoding_options = { 0 };//encoding_options.version = 0;//encoding_options.save_alpha_channel = false;//encoding_options.image_orientation = heif_orientation_normal; // 例如:设置图像方向为正常// 创建HEIF编码器struct heif_encoder* encoder;err = heif_context_get_encoder_for_format(ctx, heif_compression_HEVC, &encoder);if (err.code != heif_error_Ok){std::cerr << "Error getting HEIF encoder: " << err.message << std::endl;heif_image_release(image);heif_context_free(ctx);return false;}heif_encoder_set_lossy_quality(encoder, 80); //0-100 压缩比例heif_encoder_set_lossless(encoder, true); // True / Falseheif_encoder_set_logging_level(encoder, 4); // log信息详细程度0-4err = heif_context_encode_image(ctx, image, encoder, nullptr, nullptr);if (err.code != heif_error_Ok) {std::cerr << "Error encoding HEIF image: " << err.message << std::endl;heif_encoder_release(encoder);heif_image_release(image);heif_context_free(ctx);return false;}err = heif_context_write_to_file(ctx, filename);if (err.code != heif_error_Ok) {std::cerr << "Error writing HEIF file: " << err.message << std::endl;heif_encoder_release(encoder);heif_image_release(image);heif_context_free(ctx);return false;}heif_encoder_release(encoder);heif_image_release(image);heif_context_free(ctx);return true;
}bool GRAYMatToHeif(cv::Mat& mat, const char* filename)
{// 确保输入的cv::Mat 是8位深度,单通道的灰度图if (mat.empty() || mat.type() != CV_8UC1) {std::cerr << "Invalid Mat format. Expected 8UC1." << std::endl;return false;}struct heif_image* image;struct heif_context* ctx = heif_context_alloc();struct heif_error err;int width = mat.cols;int height = mat.rows;// 创建HEIF图像err = heif_image_create(width, height, heif_colorspace_monochrome, heif_chroma_monochrome, &image);if (err.code != heif_error_Ok) {std::cerr << "Error creating HEIF image: " << err.message << std::endl;heif_context_free(ctx);return false;}// 添加一个用于灰度通道的图像平面err = heif_image_add_plane(image, heif_channel_Y, width, height, 8);if (err.code != heif_error_Ok) {std::cerr << "Error adding plane to HEIF image: " << err.message << std::endl;heif_image_release(image);heif_context_free(ctx);return false;}// 获取指向HEIF图像灰度数据的指针int stride;uint8_t* p = heif_image_get_plane(image, heif_channel_Y, &stride);// 将cv::Mat 的灰度数据复制到HEIF图像中for (int y = 0; y < height; y++) {memcpy(p + y * stride, mat.ptr(y), width); // 每行的像素数据是 width 个字节}// 创建HEIF编码器struct heif_encoder* encoder;err = heif_context_get_encoder_for_format(ctx, heif_compression_HEVC, &encoder);if (err.code != heif_error_Ok) {std::cerr << "Error getting HEIF encoder: " << err.message << std::endl;heif_image_release(image);heif_context_free(ctx);return false;}heif_encoder_set_lossy_quality(encoder, 80); //0-100 压缩比例heif_encoder_set_lossless(encoder, true); // True / Falseheif_encoder_set_logging_level(encoder, 4); // log信息详细程度0-4err = heif_context_encode_image(ctx, image, encoder, nullptr, nullptr);if (err.code != heif_error_Ok) {std::cerr << "Error encoding HEIF image: " << err.message << std::endl;heif_encoder_release(encoder);heif_image_release(image);heif_context_free(ctx);return false;}err = heif_context_write_to_file(ctx, filename);if (err.code != heif_error_Ok) {std::cerr << "Error writing HEIF file: " << err.message << std::endl;heif_encoder_release(encoder);heif_image_release(image);heif_context_free(ctx);return false;}heif_encoder_release(encoder);heif_image_release(image);heif_context_free(ctx);return true;}cv::Mat HeifToRGBMat(const char* filename)
{// 创建HEIF上下文heif_context* ctx = heif_context_alloc();heif_error error = heif_context_read_from_file(ctx, filename, nullptr);if (error.code != heif_error_Ok){std::cerr << "读取heif文件失败:" << error.message << std::endl;heif_context_free(ctx);return cv::Mat();}// 获取图像句柄heif_image_handle* handle;error = heif_context_get_primary_image_handle(ctx, &handle);if (error.code != heif_error_Ok){std::cerr << "获取图像句柄失败:" << error.message << std::endl;heif_context_free(ctx);return cv::Mat();}// 解码图像heif_image* image;error = heif_decode_image(handle, &image, heif_colorspace_RGB, heif_chroma_interleaved_RGB, nullptr);if (error.code != heif_error_Ok){std::cerr << "解码图像失败:" << error.message << std::endl;heif_image_handle_release(handle);heif_context_free(ctx);return cv::Mat();}// 获取图像宽度、高度和数据int width = heif_image_get_width(image, heif_channel_interleaved);int height = heif_image_get_height(image, heif_channel_interleaved);int stride;const uint8_t* data = heif_image_get_plane_readonly(image, heif_channel_interleaved, &stride);// 将图像数据复制到cv::Matcv::Mat mat(height, width, CV_8UC3);for (int y = 0; y < height; y++) {memcpy(mat.ptr(y), data + y * stride, width * 3);}cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB);//释放资源heif_image_release(image);heif_image_handle_release(handle);heif_context_free(ctx);return mat;
}cv::Mat HeifToGRAYMat(const char* filename)
{// 创建HEIF上下文heif_context* ctx = heif_context_alloc();heif_error error = heif_context_read_from_file(ctx, filename, nullptr);if (error.code != heif_error_Ok) {std::cerr << "读取HEIF文件失败: " << error.message << std::endl;heif_context_free(ctx);return cv::Mat();}// 获取第一个图像句柄heif_image_handle* handle;error = heif_context_get_primary_image_handle(ctx, &handle);if (error.code != heif_error_Ok) {std::cerr << "获取图像句柄失败:" << error.message << std::endl;heif_context_free(ctx);return cv::Mat();}// 解码图像heif_image* image;error = heif_decode_image(handle, &image, heif_colorspace_monochrome, heif_chroma_monochrome, nullptr);if (error.code != heif_error_Ok) {std::cerr << "解码图像失败: " << error.message << std::endl;heif_image_handle_release(handle);heif_context_free(ctx);return cv::Mat();}// 获取图像宽度、高度和数据int width = heif_image_get_width(image, heif_channel_Y);int height = heif_image_get_height(image, heif_channel_Y);int stride;const uint8_t* data = heif_image_get_plane_readonly(image, heif_channel_Y, &stride);// 将图像数据复制到 cv::Matcv::Mat mat(height, width, CV_8UC1);for (int y = 0; y < height; y++) {memcpy(mat.ptr(y), data + y * stride, width);}cv::imwrite("C:\\Users\\Lenovo\\Desktop\\opencv_decode.png", mat);// 释放资源heif_image_release(image);heif_image_handle_release(handle);heif_context_free(ctx);return mat;
}int main()
{// RGBcv::Mat matRGB;cv::Mat matBGR = cv::imread("C:\\Users\\Lenovo\\Desktop\\opencv.png");const char* rgbFilename = "C:\\Users\\Lenovo\\Desktop\\opencv.heif";const char* dstRgbFilename = "C:\\Users\\Lenovo\\Desktop\\opencv_decode.png";cv::cvtColor(matBGR, matRGB, cv::COLOR_BGR2RGB);bool isRGB = RGBMatToHeif(matRGB, rgbFilename);matBGR = HeifToRGBMat(rgbFilename);cv::imwrite(dstRgbFilename, matBGR);// GRAYcv::Mat matGRAY = cv::imread("C:\\Users\\Lenovo\\Desktop\\opencv_gray.png", cv::IMREAD_GRAYSCALE);const char* grayFilename = "C:\\Users\\Lenovo\\Desktop\\opencv_gray.heif";const char* dstGrayFilename = "C:\\Users\\Lenovo\\Desktop\\opencv_gray_decode.png";bool isGRAY = GRAYMatToHeif(matGRAY, grayFilename);cv::Mat dstMatGRAY = HeifToGRAYMat(grayFilename);cv::imwrite(dstGrayFilename, dstMatGRAY);return 0;
}
相关文章:
opencv Mat To Heif
高效率图像文件格式(英语:High Efficiency Image File Format, HEIF;也称高效图像文件格式)是一个用于单张图像或图像序列的文件格式。它由运动图像专家组(MPEG)开发,并在MPEG-H Part 12&#x…...
二刷代码随想录第24天
93. 复原 IP 地址 确定函数is_ip的实现细节,start不能超过end,没有0开头的非0数字,每个字符都在0-9之间,每段字符小于255在原字符串s上做操作会更简单一些 class Solution { public:vector<string> result;vector<string> rest…...
Java设计模式之状态模式架构高扩展的订单状态管理
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c=1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编程,高并发设计,Springboot和微服务,熟悉Linux,ESXI虚拟化以及云原生Docker和K8s…...
Yagmail邮件发送库:如何用Python实现自动化邮件营销?
目录 一、Yagmail简介 二、安装Yagmail 三、基本使用示例 1. 发送简单文本邮件 2. 发送HTML邮件 3. 发送带有附件的邮件 4. 多收件人处理 5. 自定义邮件头 四、高级功能 1. SMTP配置 2. 邮件模板 3. OAuth2认证 五、自动化邮件营销案例 六、错误处理和调试 七、…...
李宏毅深度学习-Pytorch Tutorial2
什么是张量? 张量(Tensor)是深度学习和机器学习中一个非常基础且重要的概念。在数学上,张量可以被看作是向量和矩阵的泛化。简单来说,张量是一种多维数组,它可以表示标量(0维)、向量…...
SaaS财务软件:赋能企业数字化转型
在数字化浪潮的推动下,企业财务管理正逐步迈向智能化、高效化的新阶段。在这个过程中,SaaS财务软件应运而生,成为许多企业的首选。以易舟云财务软件为例,这款软件不仅集成了众多先进的财务管理功能,而且在用户体验上做…...
FPGA实战篇(按键控制LDE实验)
1.按键简介 按键开关是一种电子开关,属于电子元器件类。我们的开发板上有两种按键开关:第一种是本实验所使用的轻触式按键开关,简称轻触开关。使用时以向开关的操作方向施加压力使内部电路闭合接通,当撤销压力时开关断开ÿ…...
在Ubuntu-22.04 [WSL2]中配置Docker
文章目录 0. 进入Ubuntu-22.041. 更新系统软件包2. 安装Docker相关依赖包3. 添加Docker官方GPG密钥4. 添加Docker软件源5. 安装Docker Engine5.1 更新软件包列表5.2 安装Docker相关软件包 6. 验证Docker安装是否成功6.1 查看Docker版本信息6.2 启动Docker6.3 配置镜像加速器6.4…...
ACM:均分纸牌
主要思路 整体思路概述: 本题旨在解决给定N堆纸牌(纸牌总数是N的倍数),通过按照特定移牌规则移动纸牌,找出用最少移动次数使每堆纸牌数量相等的方法。程序采用了一种逐步调整的思路,先计算出每堆纸牌应有的…...
ThreadFactory
ThreadFactory 是 Java 中一个用于创建线程的接口,它可以自定义线程的创建过程,例如线程的名称、优先级、是否为守护线程等。它是 java.util.concurrent 包的一部分,通常与线程池(ThreadPoolExecutor)一起使用。 线程…...
WEB开发: Node.js路由之由浅入深(一) - 全栈工程师入门
作为一个使用Node.js多年的开发者,我已经习惯于用Node.js写一些web应用来为工作服务,因为实现快速、部署简单、自定义强。今天我们一起来学习一个全栈工程师必备技能:web路由。(观看此文的前提是默认你已经装好nonde.js了…...
NES游戏机项目制作笔记(未完成)
24年12月1日晚记——在网上找项目学习的时候发现一个有意思的项目,准备靠这个应用一些STM32的高级功能。值得提醒的是——目的在于学习不可贪杯,注意效率 01 根据项目需求分析 为确保充分考虑每一个细节,并且让自己高效的完成项目制作&#…...
云服务器部署upload-labs-docker(文件上传靶场)环境 以及相关报错问题
环境的搭建 准备:云服务器(本地的linux服务器(版本最好不要是老的不然不兼容docker)) f8x配置docker环境: https://github.com/ffffffff0x/f8x 一键配置 docker拉取file-labs靶场 https://github.com…...
Elasticsearch入门之HTTP基础操作
RESTful REST 指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是 RESTful。Web 应用程序最重要的 REST 原则是,客户端和服务器之间的交互在请求之间是无状态的。从客户端到服务器的每个请求都必须包含理解请求所必需的信息。如果服务器在…...
maven聚合项目部署到tomcat上
目录 一.聚合项目 1.检查无误后将项目打包 2.将这四个拷贝到tomcat的webapp下 二.启动tomcat 1.双击startup.bat 2.页面访问http://localhost:8080 3.打开webapp文件夹,发现多了三个文件夹 4.点进去才有要访问的index页面 5.再进行访问 解决: …...
基于Matlab生育模型和年龄别死亡率的未来人口预测与结构动态分析
人口预测在社会经济发展、政策规划以及资源分配中扮演着至关重要的角色,特别是在全球人口老龄化、少子化趋势日益显著的背景下,对人口增长规律及结构变化的研究愈发重要。人口结构的变化不仅直接影响劳动力供给和经济增长潜力,还对医疗、教育…...
公共服务 kkFileView 4.1 文件预览 Docker 一键部署
官方文档 https://kkview.cn/zh-cn/docs/production.html 镜像导入 # 网络环境方便访问docker中央仓库 docker pull keking/kkfileview:4.1.0# 网络环境不方便访问docker中央仓库 wget https://kkview.cn/resource/kkFileView-4.1.0-docker.tar docker load -i kkFileView-4…...
福昕PDF低代码平台
福昕PDF低代码平台简介 福昕PDF 低代码平台是一款创新的工具,旨在简化PDF处理和管理的流程。通过这个平台,用户可以通过简单的拖拽界面上的按钮,轻松完成对Cloud API的调用工作流,而无需编写复杂的代码。这使得即使没有编程经验的…...
Ubuntu环境安装RabbitMQ
1.安装Erlang RabbitMq需要Erlang语⾔的⽀持,在安装rabbitMq之前需要安装erlang # 更新软件包 sudo apt-get update # 安装 erlang sudo apt-get install erlang 查看erlang版本 : erl 退出命令:halt(). 2. 安装RabbitMQ # 更新软件包 sudo apt-get update # 安装 …...
集合ArrayList
黑马程序员Java的个人笔记 BV17F411T7Ao p111~p115 目录 集合存储数据类型的特点 创建对象 ArrayList 成员方法 .add 增加元素 .remove 删除元素 .set 修改元素 .get 查询元素 .size 获取长度 基本数据类型对应的包装类 Character 练习 返回多个数据 集合存储…...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...
论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...
【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...
