【一秒梵高】基于OpenCV4实现图像九种风格迁移

风格迁移

图像风格迁移、色彩填充与色彩变换等,严格意义上来说都属于计算机视觉任务中图像处理的分支。它们输入的是图像,输出的也是图像,过程实现图像到图像的内容与风格的转换,深度学习在这类图像处理任务上也取得了良好的效果。OpenCV4在DNN模块中支持常见风格迁移的图像转换模型,该模型是李飞飞等人发表的感知损失实时分割迁移与超分辨率论文的torch版本实现,模型的下载地址为:

https://github.com/jcjohnson/fast-neural-style

模型介绍

模型支持任意尺寸的图像输入,输出NCHW的四维数据,其中N=1,C=3表示彩色图像,H跟W分别表示图像的高与宽。作者提供了很多种预训练的风格迁移模型以供读者使用,这里下载了下面九种风格转换的预训练模型:

composition_vii.t7
starry_night.t7
la_muse.t7
the_wave.t7
mosaic.t7
the_scream.t7
feathers.t7
candy.t7
udnie.t7

在这里插入图片描述
这些模型都是torch框架支持的二进制权重文件,加载模型之后,就可以调用forward得到结果,通过对输出结果反向加上均值,rescale到0~255的RGB色彩空间,即可得到转换后的风格图像,如图12-8所示,是九种变换风格的效果演示。
在这里插入图片描述
OpenCV4 C++ 风格迁移演示的相关代码如下:

int main(int argc, char** argv) {
	int index = 0;
	VideoCapture capture = VideoCapture(0);
	Net net = readNetFromTorch(format("%s%s", base_dir.c_str(), styles[index].c_str()));
	net.setPreferableBackend(DNN_BACKEND_INFERENCE_ENGINE);
	net.setPreferableTarget(DNN_TARGET_CPU);
	Mat frame;
	while (true) {
		capture.read(frame);
		imshow("input", frame);
		Mat blobImage = blobFromImage(frame, 1.0,
			Size(width, height),
			Scalar(103.939, 116.779, 123.68), false, false);

		net.setInput(blobImage);
		Mat out = net.forward();
		vector<double> layersTimings;
		double freq = getTickFrequency() / 1000;
		double time = net.getPerfProfile(layersTimings) / freq;
		printf("execute time : %.2f ms\n", time);
		int ch = out.size[1];
		int h = out.size[2];
		int w = out.size[3];
		Mat result = Mat::zeros(Size(w, h), CV_32FC3);
		float* data = out.ptr<float>();

		// decode 4-d Mat object
		for (int c = 0; c < ch; c++) {
			for (int row = 0; row < h; row++) {
				for (int col = 0; col < w; col++) {
					result.at<Vec3f>(row, col)[c] = *data++;
				}
			}
		}

		// 整合结果输出
		printf("channels : %d, height: %d, width: %d \n", ch, h, w);
		add(result, Scalar(103.939, 116.779, 123.68), result);
		result /= 255.0;

		// 中值滤波
		medianBlur(result, result, 5);
		Mat dst;
		resize(result, dst, frame.size());
		imshow("styled-video", dst);

		// ESC means exit
		char c = waitKey(1);
		if (c == 27) {
			break;
		}
	}

	waitKey(0);
	return 0;
}

以上演示来自《OpenCV应用开发:入门、进阶与工程化实践》一书第十二章 第五小节内容。学习OpenCV深度神经网络模型推理技能,相关代码解释与说明查看本书即可获取,

七折优惠专属《OpenCV应用开发:入门、进阶与工程化实践》

关于本书

《OpenCV应用开发:入门、进阶与工程化实践》全书共计16个章节,重点聚焦OpenCV开发常用模块详解与工程化开发实践,提升OpenCV应用开发能力,助力读者成为OpenCV开发者,同时包含深度学习模型训练与部署加速等知识,帮助OpenCV开发者进一步拓展技能地图,满足工业项目落地所需技能提升。请点下面查看本书目录

七折优惠专属《OpenCV应用开发:入门、进阶与工程化实践》

学习课程有专属答疑群
读者专属QQ群 :657875553
进群暗号:OpenCV4读者

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
图像风格迁移是一种将一副图像的内容特征与另一副图像的风格特征相结合,生成一副新的图像的技术。在OpenCV中,可以使用卷积神经网络(CNN)来实现图像风格迁移实现图像风格迁移的原理如下: 1. 预训练模型:首先,需要使用一个预训练的卷积神经网络模型,例如VGGNet,来提取图像的内容特征和风格特征。这些特征可以通过在网络中的不同层次上提取特征图来获得。 2. 内容特征提取:选择预训练模型中的某一层作为内容特征提取层。将待处理的图像输入到模型中,获取该层的特征图。这些特征图表示了图像的内容信息。 3. 风格特征提取:选择预训练模型中的多个层作为风格特征提取层。将风格图像输入到模型中,获取这些层的特征图。这些特征图表示了图像的风格信息。 4. 内容损失计算:通过计算生成图像与原始图像在内容特征层的特征图之间的差异,来衡量生成图像与原始图像的内容相似度。可以使用均方误差(MSE)来计算内容损失。 5. 风格损失计算:通过计算生成图像与风格图像在风格特征层的特征图之间的差异,来衡量生成图像与风格图像的风格相似度。可以使用Gram矩阵来计算特征图之间的相关性,并使用均方误差(MSE)来计算风格损失。 6. 总损失计算:将内容损失和风格损失加权相加,得到总损失。通过最小化总损失,可以优化生成图像,使其同时具有原始图像的内容特征和风格图像的风格特征。 7. 优化过程:使用梯度下降等优化算法,不断调整生成图像的像素值,使其逐渐接近最优解。 下面是一个使用OpenCV实现图像风格迁移的示例代码: ```python import cv2 import numpy as np # 加载原始图像和风格图像 content_image = cv2.imread('content.jpg') style_image = cv2.imread('style.jpg') # 定义内容特征提取层和风格特征提取层 content_layers = ['conv4_2'] style_layers = ['conv1_1', 'conv2_1', 'conv3_1', 'conv4_1', 'conv5_1'] # 加载预训练模型 net = cv2.dnn.readNetFromCaffe('VGGNet.prototxt', 'VGGNet.caffemodel') # 提取内容特征 content_features = {} for layer in content_layers: blob = cv2.dnn.blobFromImage(content_image, 1.0, (224, 224), (104, 117, 123), False) net.setInput(blob) output = net.forward(layer) content_features[layer] = output # 提取风格特征 style_features = {} for layer in style_layers: blob = cv2.dnn.blobFromImage(style_image, 1.0, (224, 224), (104, 117, 123), False) net.setInput(blob) output = net.forward(layer) style_features[layer] = output # 计算内容损失和风格损失 content_loss = 0 for layer in content_layers: content_loss += np.mean((content_features[layer] - generated_features[layer]) ** 2) style_loss = 0 for layer in style_layers: gram_style = np.matmul(style_features[layer].reshape(-1, style_features[layer].shape[3]), style_features[layer].reshape(style_features[layer].shape[3], -1)) gram_generated = np.matmul(generated_features[layer].reshape(-1, generated_features[layer].shape[3]), generated_features[layer].reshape(generated_features[layer].shape[3], -1)) style_loss += np.mean((gram_style - gram_generated) ** 2) total_loss = content_loss + style_loss # 优化生成图像 optimizer = cv2.optflow.createOptFlow_DeepFlow() generated_image = content_image.copy() for i in range(100): gradient = optimizer.calc(generated_image, total_loss) generated_image -= gradient # 显示生成图像 cv2.imshow('Generated Image', generated_image) cv2.waitKey(0) cv2.destroyAllWindows() ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gloomyfish

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值