VS2022中OpenCV4.5.5 C++找不到dnn_superres.hpp如何实现超分辨率
问题原因
OpenCV 4.5.5官方默认发布的预编译包仅包含主仓库模块,dnn_superres属于opencv_contrib扩展仓库中的模块,默认安装不会部署该模块对应的头文件、lib和dll文件,因此编译时会抛出找不到opencv2/dnn_superres.hpp的错误。
可用解决方案
方案1:编译集成opencv_contrib扩展,使用封装好的dnn_superres接口
- 下载和当前OpenCV版本完全一致的opencv_contrib 4.5.5源码,版本不匹配会出现编译兼容问题
- 打开CMake配置OpenCV编译项,找到
OPENCV_EXTRA_MODULES_PATH配置项,填入解压后opencv_contrib目录下的modules文件夹绝对路径 - 按需勾选需要编译的模块(可取消其他不需要的contrib模块减少编译耗时),配置完成后生成Visual Studio 2022工程
- 打开生成的VS工程,分别编译Debug、Release版本,将编译产出的include、lib、dll文件替换本地原有OpenCV对应路径的文件
- 在VS2022项目的附加依赖项中补充链接
opencv_dnn_superres455d.lib(Debug配置)和opencv_dnn_superres455.lib(Release配置) - 配置完成后即可正常引入头文件调用接口,基础调用示例:
#include <opencv2/dnn_superres.hpp> #include <opencv2/imgcodecs.hpp> #include <opencv2/highgui.hpp> int main() { cv::dnn_superres::DnnSuperResImpl sr; // 加载对应超分预训练模型,支持ESPCN、EDSR、FSRCNN、LapSRN等 sr.readModel("EDSR_x4.pb"); // 设置模型类型和超分倍率 sr.setModel("edsr", 4); cv::Mat input_img = cv::imread("input.jpg"); cv::Mat super_res_img; sr.upsample(input_img, super_res_img); cv::imwrite("sr_result.png", super_res_img); return 0; }
编译时如果遇到文件下载失败的问题,可以手动下载对应依赖文件放到CMake提示的缓存目录后重新配置即可。
方案2:不依赖扩展模块,直接用OpenCV内置dnn模块实现超分
如果不想重新编译OpenCV,可以直接使用4.5.5版本主模块自带的dnn接口加载超分模型完成推理,不需要额外安装扩展,操作步骤如下:
- 提前准备好ONNX或PB格式的超分预训练模型,确认模型的输入输出节点、预处理要求
- 调用内置dnn接口完成图像预处理、模型推理、结果后处理即可,基础示例代码:
#include <opencv2/dnn.hpp> #include <opencv2/imgproc.hpp> #include <opencv2/imgcodecs.hpp> #include <opencv2/highgui.hpp> int main() { // 加载ONNX格式超分模型 cv::dnn::Net sr_net = cv::dnn::readNetFromONNX("espcn_x4.onnx"); cv::Mat input_img = cv::imread("input.jpg"); // 按模型要求做预处理:归一化、转换NCHW blob格式 cv::Mat input_blob; cv::dnn::blobFromImage(input_img, input_blob, 1.0/255.0, input_img.size(), cv::Scalar(), true, false); sr_net.setInput(input_blob); cv::Mat output_blob = sr_net.forward(); // 后处理:将输出blob转换为标准Mat图像格式 std::vector<cv::Mat> channel_mats; int out_h = output_blob.size[2]; int out_w = output_blob.size[3]; for (int i = 0; i < 3; i++) { cv::Mat ch(out_h, out_w, CV_32F, output_blob.ptr(0, i)); channel_mats.push_back(ch); } cv::Mat super_res_img; cv::merge(channel_mats, super_res_img); super_res_img.convertTo(super_res_img, CV_8U, 255.0); cv::cvtColor(super_res_img, super_res_img, cv::COLOR_RGB2BGR); cv::imwrite("sr_result.png", super_res_img); return 0; }
两种方案选择参考:方案1接口封装完善,不需要手动处理模型前后处理逻辑,调用简单,但需要重新编译OpenCV;方案2无需额外编译扩展,灵活性高,但需要根据所用模型的输入输出要求自行调整前后处理逻辑。
内容的提问来源于stack exchange,提问作者Krupali Mistry
相关产品推荐
相关产品推荐

