当前位置: 首页 > news >正文

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

高效率图像文件格式&#xff08;英语&#xff1a;High Efficiency Image File Format, HEIF&#xff1b;也称高效图像文件格式&#xff09;是一个用于单张图像或图像序列的文件格式。它由运动图像专家组&#xff08;MPEG&#xff09;开发&#xff0c;并在MPEG-H Part 12&#x…...

二刷代码随想录第24天

93. 复原 IP 地址 确定函数is_ip的实现细节&#xff0c;start不能超过end&#xff0c;没有0开头的非0数字&#xff0c;每个字符都在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

什么是张量&#xff1f; 张量&#xff08;Tensor&#xff09;是深度学习和机器学习中一个非常基础且重要的概念。在数学上&#xff0c;张量可以被看作是向量和矩阵的泛化。简单来说&#xff0c;张量是一种多维数组&#xff0c;它可以表示标量&#xff08;0维&#xff09;、向量…...

SaaS财务软件:赋能企业数字化转型

在数字化浪潮的推动下&#xff0c;企业财务管理正逐步迈向智能化、高效化的新阶段。在这个过程中&#xff0c;SaaS财务软件应运而生&#xff0c;成为许多企业的首选。以易舟云财务软件为例&#xff0c;这款软件不仅集成了众多先进的财务管理功能&#xff0c;而且在用户体验上做…...

FPGA实战篇(按键控制LDE实验)

1.按键简介 按键开关是一种电子开关&#xff0c;属于电子元器件类。我们的开发板上有两种按键开关&#xff1a;第一种是本实验所使用的轻触式按键开关&#xff0c;简称轻触开关。使用时以向开关的操作方向施加压力使内部电路闭合接通&#xff0c;当撤销压力时开关断开&#xff…...

在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:均分纸牌

主要思路 整体思路概述&#xff1a; 本题旨在解决给定N堆纸牌&#xff08;纸牌总数是N的倍数&#xff09;&#xff0c;通过按照特定移牌规则移动纸牌&#xff0c;找出用最少移动次数使每堆纸牌数量相等的方法。程序采用了一种逐步调整的思路&#xff0c;先计算出每堆纸牌应有的…...

ThreadFactory

ThreadFactory 是 Java 中一个用于创建线程的接口&#xff0c;它可以自定义线程的创建过程&#xff0c;例如线程的名称、优先级、是否为守护线程等。它是 java.util.concurrent 包的一部分&#xff0c;通常与线程池&#xff08;ThreadPoolExecutor&#xff09;一起使用。 线程…...

WEB开发: Node.js路由之由浅入深(一) - 全栈工程师入门

作为一个使用Node.js多年的开发者&#xff0c;我已经习惯于用Node.js写一些web应用来为工作服务&#xff0c;因为实现快速、部署简单、自定义强。今天我们一起来学习一个全栈工程师必备技能&#xff1a;web路由。&#xff08;观看此文的前提是默认你已经装好nonde.js了&#xf…...

NES游戏机项目制作笔记(未完成)

24年12月1日晚记——在网上找项目学习的时候发现一个有意思的项目&#xff0c;准备靠这个应用一些STM32的高级功能。值得提醒的是——目的在于学习不可贪杯&#xff0c;注意效率 01 根据项目需求分析 为确保充分考虑每一个细节&#xff0c;并且让自己高效的完成项目制作&#…...

云服务器部署upload-labs-docker(文件上传靶场)环境 以及相关报错问题

环境的搭建 准备&#xff1a;云服务器&#xff08;本地的linux服务器&#xff08;版本最好不要是老的不然不兼容docker&#xff09;&#xff09; f8x配置docker环境&#xff1a; https://github.com/ffffffff0x/f8x 一键配置 docker拉取file-labs靶场 https://github.com…...

Elasticsearch入门之HTTP基础操作

RESTful REST 指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是 RESTful。Web 应用程序最重要的 REST 原则是&#xff0c;客户端和服务器之间的交互在请求之间是无状态的。从客户端到服务器的每个请求都必须包含理解请求所必需的信息。如果服务器在…...

maven聚合项目部署到tomcat上

目录 一.聚合项目 1.检查无误后将项目打包 2.将这四个拷贝到tomcat的webapp下 二.启动tomcat 1.双击startup.bat 2.页面访问http://localhost:8080 3.打开webapp文件夹&#xff0c;发现多了三个文件夹 4.点进去才有要访问的index页面 5.再进行访问 解决&#xff1a; …...

基于Matlab生育模型和年龄别死亡率的未来人口预测与结构动态分析

人口预测在社会经济发展、政策规划以及资源分配中扮演着至关重要的角色&#xff0c;特别是在全球人口老龄化、少子化趋势日益显著的背景下&#xff0c;对人口增长规律及结构变化的研究愈发重要。人口结构的变化不仅直接影响劳动力供给和经济增长潜力&#xff0c;还对医疗、教育…...

公共服务 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 低代码平台是一款创新的工具&#xff0c;旨在简化PDF处理和管理的流程。通过这个平台&#xff0c;用户可以通过简单的拖拽界面上的按钮&#xff0c;轻松完成对Cloud API的调用工作流&#xff0c;而无需编写复杂的代码。这使得即使没有编程经验的…...

Ubuntu环境安装RabbitMQ

1.安装Erlang RabbitMq需要Erlang语⾔的⽀持&#xff0c;在安装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 练习 返回多个数据 集合存储…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...

【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制

使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下&#xff0c;限制某个 IP 的访问频率是非常重要的&#xff0c;可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案&#xff0c;使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...

LabVIEW双光子成像系统技术

双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制&#xff0c;展现出显著的技术优势&#xff1a; 深层组织穿透能力&#xff1a;适用于活体组织深度成像 高分辨率观测性能&#xff1a;满足微观结构的精细研究需求 低光毒性特点&#xff1a;减少对样本的损伤…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)

引言 工欲善其事&#xff0c;必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后&#xff0c;我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集&#xff0c;就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...