OpenCV-图像着色(采用DNN模块导入深度学习模型)

简介: OpenCV-图像着色(采用DNN模块导入深度学习模型)

实现原理

      图像着色最早是应用在图像修复方面,将一些过去的黑白旧照根据预设色盘上色,得到色彩饱满的彩色图,比如0灰度对应某个RGB数值,120灰度对应某个RGB数值等等,这也是当前OpenCV中已集成好的applycolormap(伪彩色函数)实现原理,按照不同的色盘给灰度图上色,可得到不同样式的伪彩色图,像当前深度图像、红外成像、雷达地图成像等领域就采用这类方法实现图像色彩重绘。


      若要将图像上色为符合现实逻辑的语义颜色和色调,就不能单单依靠固定的色盘方法,过去常采用的方案一般是依赖人主观的上色能力,就如PS中,可以通过控制色彩曲线、颜色占比等方法将黑白图慢慢恢复成彩色图。而随着深度学习、计算机视觉近几年的快速发展,将灰度图智能且高效地上色成为可能。基于图像着色算法和caffe、tensorflow、pytorch等深度学习框架,将相关的巨量数据集训练成具备一定预测能力的深度学习模型,通过这些模型即可实现更优的图像着色效果。


      本文通过OpenCV中DNN模块导入深度学习模型的方法,来实现图像着色效果。


具体流程

      1)加载模型信息,模型下载链接在下方,若不想用钱下载可以三连,评论留下邮箱我会尽快发送完整模型文件,确保打开即用。

string modelTxt = "colorization_deploy_v2.prototxt";
string modelBin = "colorization_release_v2.caffemodel";
Net net = dnn::readNetFromCaffe(modelTxt, modelBin);

     2)设置相关参数。

const int W_in = 224;
const int H_in = 224;
int sz[] = { 2, 313, 1, 1 };
const Mat Pts_in_hull(4, sz, CV_32F, pts_in_hull);
Ptr<dnn::Layer> class8_ab = net.getLayer("class8_ab");
class8_ab->blobs.emplace_back(Pts_in_hull);
Ptr<dnn::Layer> conv8_313_rh = net.getLayer("conv8_313_rh");
conv8_313_rh->blobs.emplace_back(Mat(1, 313, CV_32F, Scalar(2.606)));

      3)将图像转化为Lab颜色空间,提取L通道操作,这样的好处是仅操作亮度即可,如果用RGB,那要同时处理三个通道的数据,而三个参数调控难度太大。

Mat lab, L, input;
img.convertTo(img, CV_32F, 1.0 / 255);
cvtColor(img, lab, COLOR_BGR2Lab);
extractChannel(lab, L, 0);
resize(L, input, Size(W_in, H_in));
input -= 50;

      4)将L通道图像输入到网络中,前向计算,从网络输出中提取a和b通道,组合成彩色图即完成。

Size siz(result.size[2], result.size[3]);
Mat a = Mat(siz, CV_32F, result.ptr(0, 0));
Mat b = Mat(siz, CV_32F, result.ptr(0, 1));
resize(a, a, img.size());
resize(b, b, img.size());
Mat color, chn[] = { L, a, b };
merge(chn, 3, lab);
cvtColor(lab, color, COLOR_Lab2BGR);

C++测试代码

#include <opencv2/dnn.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace cv::dnn;
using namespace std;
// 通过pts_in_hull.npy转化
static float pts_in_hull[] = {
  -90., -90., -90., -90., -90., -80., -80., -80., -80., -80., -80., -80., -80., -70., -70., -70., -70., -70., -70., -70., -70.,
  -70., -70., -60., -60., -60., -60., -60., -60., -60., -60., -60., -60., -60., -60., -50., -50., -50., -50., -50., -50., -50., -50.,
  -50., -50., -50., -50., -50., -50., -40., -40., -40., -40., -40., -40., -40., -40., -40., -40., -40., -40., -40., -40., -40., -30.,
  -30., -30., -30., -30., -30., -30., -30., -30., -30., -30., -30., -30., -30., -30., -30., -20., -20., -20., -20., -20., -20., -20.,
  -20., -20., -20., -20., -20., -20., -20., -20., -20., -10., -10., -10., -10., -10., -10., -10., -10., -10., -10., -10., -10., -10.,
  -10., -10., -10., -10., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 10., 10., 10., 10., 10., 10., 10.,
  10., 10., 10., 10., 10., 10., 10., 10., 10., 10., 10., 20., 20., 20., 20., 20., 20., 20., 20., 20., 20., 20., 20., 20., 20., 20.,
  20., 20., 20., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 30., 40., 40., 40., 40.,
  40., 40., 40., 40., 40., 40., 40., 40., 40., 40., 40., 40., 40., 40., 40., 40., 50., 50., 50., 50., 50., 50., 50., 50., 50., 50.,
  50., 50., 50., 50., 50., 50., 50., 50., 50., 60., 60., 60., 60., 60., 60., 60., 60., 60., 60., 60., 60., 60., 60., 60., 60., 60.,
  60., 60., 60., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 70., 80., 80., 80.,
  80., 80., 80., 80., 80., 80., 80., 80., 80., 80., 80., 80., 80., 80., 80., 80., 90., 90., 90., 90., 90., 90., 90., 90., 90., 90.,
  90., 90., 90., 90., 90., 90., 90., 90., 90., 100., 100., 100., 100., 100., 100., 100., 100., 100., 100., 50., 60., 70., 80., 90.,
  20., 30., 40., 50., 60., 70., 80., 90., 0., 10., 20., 30., 40., 50., 60., 70., 80., 90., -20., -10., 0., 10., 20., 30., 40., 50.,
  60., 70., 80., 90., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., 80., 90., 100., -40., -30., -20., -10., 0., 10., 20.,
  30., 40., 50., 60., 70., 80., 90., 100., -50., -40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., 80., 90., 100., -50.,
  -40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., 80., 90., 100., -60., -50., -40., -30., -20., -10., 0., 10., 20.,
  30., 40., 50., 60., 70., 80., 90., 100., -70., -60., -50., -40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., 80., 90.,
  100., -80., -70., -60., -50., -40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., 80., 90., -80., -70., -60., -50.,
  -40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., 80., 90., -90., -80., -70., -60., -50., -40., -30., -20., -10.,
  0., 10., 20., 30., 40., 50., 60., 70., 80., 90., -100., -90., -80., -70., -60., -50., -40., -30., -20., -10., 0., 10., 20., 30.,
  40., 50., 60., 70., 80., 90., -100., -90., -80., -70., -60., -50., -40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70.,
  80., -110., -100., -90., -80., -70., -60., -50., -40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., 80., -110., -100.,
  -90., -80., -70., -60., -50., -40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., 80., -110., -100., -90., -80., -70.,
  -60., -50., -40., -30., -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., -110., -100., -90., -80., -70., -60., -50., -40., -30.,
  -20., -10., 0., 10., 20., 30., 40., 50., 60., 70., -90., -80., -70., -60., -50., -40., -30., -20., -10., 0.
};
int main()
{
  string modelTxt = "colorization_deploy_v2.prototxt";
  string modelBin = "colorization_release_v2.caffemodel";
  string imageFile = "test.jpg";
  string original = "zhu.jpg";
  // 读取灰度图用来作颜色还原
  Mat gray = imread(original, 0);
  // 原图对比
  Mat ori = imread(original);
  imwrite(imageFile, gray);
  Mat img = imread(imageFile);
  if (img.empty()) {
    cout << "Can't read image from file: " << imageFile << endl;
    return 2;
  }
  // 预训练网络的固定输入大小
  const int W_in = 224;
  const int H_in = 224;
  Net net = dnn::readNetFromCaffe(modelTxt, modelBin);
  // 设置训练得到的参数数据
  int sz[] = { 2, 313, 1, 1 };
  const Mat Pts_in_hull(4, sz, CV_32F, pts_in_hull);
  Ptr<dnn::Layer> class8_ab = net.getLayer("class8_ab");
  class8_ab->blobs.emplace_back(Pts_in_hull);
  Ptr<dnn::Layer> conv8_313_rh = net.getLayer("conv8_313_rh");
  conv8_313_rh->blobs.emplace_back(Mat(1, 313, CV_32F, Scalar(2.606)));
  // 提取L通道灰度图,并均值化
  Mat lab, L, input;
  img.convertTo(img, CV_32F, 1.0 / 255);
  cvtColor(img, lab, COLOR_BGR2Lab);
  extractChannel(lab, L, 0);
  resize(L, input, Size(W_in, H_in));
  input -= 50;
  // L通道图像输入到网络,前向计算
  Mat inputBlob = blobFromImage(input);
  net.setInput(inputBlob);
  Mat result = net.forward();
  // 从网络输出中提取得到的a,b通道
  Size siz(result.size[2], result.size[3]);
  Mat a = Mat(siz, CV_32F, result.ptr(0, 0));
  Mat b = Mat(siz, CV_32F, result.ptr(0, 1));
  resize(a, a, img.size());
  resize(b, b, img.size());
  // 通道合并转换成彩色图
  Mat color, chn[] = { L, a, b };
  merge(chn, 3, lab);
  cvtColor(lab, color, COLOR_Lab2BGR);
  // 结果展示
  color.convertTo(color, CV_8U, 255.);
  imshow("color", color);
  imshow("gray", gray);
  imshow("ori", ori);
  waitKey();
  return 0;
}

测试效果

图1 原图

图2 灰度图

图3 着色图

      不难看出,还原的着色图还是比较符合现实语义色调的,不过还是同原图的一些色彩有所差异,毕竟数据量有限。这个数据集当初估计没少放黄色调的图,处理了好多图像都偏暗黄系。


      注意:测试中发现,OpenCV版本为4以上,debug和release都没问题;3.4版本的debug没问题,release总是报错。所以建议用OpenCV4。

相关文章
|
2月前
|
机器学习/深度学习 TensorFlow 算法框架/工具
深度学习中的图像风格迁移
【9月更文挑战第26天】本文将探讨如何利用深度学习技术,实现图像风格的转换。我们将从基础的理论出发,然后逐步深入到具体的实现过程,最后通过代码实例来展示这一技术的实际应用。无论你是初学者还是有经验的开发者,都能在这篇文章中找到有价值的信息。让我们一起探索深度学习的奥秘吧!
|
28天前
|
计算机视觉
Opencv学习笔记(三):图像二值化函数cv2.threshold函数详解
这篇文章详细介绍了OpenCV库中的图像二值化函数`cv2.threshold`,包括二值化的概念、常见的阈值类型、函数的参数说明以及通过代码实例展示了如何应用该函数进行图像二值化处理,并展示了运行结果。
265 0
Opencv学习笔记(三):图像二值化函数cv2.threshold函数详解
|
1月前
|
机器学习/深度学习 人工智能 TensorFlow
利用深度学习实现图像风格迁移
【8月更文挑战第73天】本文通过深入浅出的方式,介绍了一种使用深度学习技术进行图像风格迁移的方法。我们将探讨如何将一张普通照片转化为具有著名画作风格的艺术作品。文章不仅解释了背后的技术原理,还提供了一个实际的代码示例,帮助读者理解如何实现这一过程。
|
2月前
|
算法 计算机视觉
opencv图像形态学
图像形态学是一种基于数学形态学的图像处理技术,它主要用于分析和修改图像的形状和结构。
46 4
|
6天前
|
机器学习/深度学习 编解码 算法
什么是超分辨率?浅谈一下基于深度学习的图像超分辨率技术
超分辨率技术旨在提升图像或视频的清晰度,通过增加单位长度内的采样点数量来提高空间分辨率。基于深度学习的方法,如SRCNN、VDSR、SRResNet等,通过卷积神经网络和残差学习等技术,显著提升了图像重建的质量。此外,基于参考图像的超分辨率技术通过利用高分辨率参考图像,进一步提高了重建图像的真实感和细节。
|
2天前
|
机器学习/深度学习 人工智能 自动驾驶
深度学习的奇迹:如何用神经网络识别图像
【10月更文挑战第33天】在这篇文章中,我们将探索深度学习的奇妙世界,特别是卷积神经网络(CNN)在图像识别中的应用。我们将通过一个简单的代码示例,展示如何使用Python和Keras库构建一个能够识别手写数字的神经网络。这不仅是对深度学习概念的直观介绍,也是对技术实践的一次尝试。让我们一起踏上这段探索之旅,看看数据、模型和代码是如何交织在一起,创造出令人惊叹的结果。
7 0
|
2月前
|
存储 计算机视觉
Opencv的基本操作(一)图像的读取显示存储及几何图形的绘制
本文介绍了使用OpenCV进行图像读取、显示和存储的基本操作,以及如何绘制直线、圆形、矩形和文本等几何图形的方法。
Opencv的基本操作(一)图像的读取显示存储及几何图形的绘制
|
2月前
|
机器学习/深度学习 并行计算 PyTorch
图像检测【YOLOv5】——深度学习
Anaconda的安装配置:(Anaconda是一个开源的Python发行版本,包括Conda、Python以及很多安装好的工具包,比如:numpy,pandas等,其中conda是一个开源包和环境管理器,可以用于在同一个电脑上安装不同版本的软件包,并且可以在不同环境之间切换,是深度学习的必备平台。) 一.Anaconda安装配置. 1.首先进入官网:https://repo.anaconda.com,选择View All Installers. 2.打开看到的界面是Anaconda的所以安装包版本,Anaconda3就代表是Python3版本,后面跟的是发行日期,我选择了最近的2022
67 28
|
23天前
|
机器学习/深度学习 数据挖掘 数据处理
深度学习之卫星图像中的环境监测
基于深度学习的卫星图像环境监测是指通过使用深度学习模型处理和分析来自卫星的遥感数据,以实现对地球环境的自动化监测和分析。这项技术极大提升了环境监测的效率、精度和规模,应用于气候变化研究、生态保护、自然灾害监测、城市扩张评估等多个领域。
60 0
|
3月前
|
算法 计算机视觉 Python
python利用opencv进行相机标定获取参数,并根据畸变参数修正图像附有全部代码(流畅无痛版)
该文章详细介绍了使用Python和OpenCV进行相机标定以获取畸变参数,并提供了修正图像畸变的全部代码,包括生成棋盘图、拍摄标定图像、标定过程和畸变矫正等步骤。
python利用opencv进行相机标定获取参数,并根据畸变参数修正图像附有全部代码(流畅无痛版)

热门文章

最新文章