智能黑白图像自动上色——C++实现

news2024/11/17 12:28:53

前言

《Colorful Image Colorization》是加里福利亚大学Richard Zhang发表在ECCV 2016上的文章,论文主要解决的问题是给灰度图的自动着色,算法并不是为恢复灰度图的真实颜色,而是用灰度图中物体的纹理、语义等信息作为线索,来预测可能的上色,最后的上色结果只要真实即可。这不仅降低了上色的难度,而且也符合人们的认知:比如一个苹果,给它上青色,上红色都是正常的,不限于某一个颜色,只要不是紫色黑色等奇怪的颜色。
在这里插入图片描述
 算法模型处理步骤是,输入图片的L通道,使用一个CNN预测对应的ab通道取值的概率分布,最后转化为RGB图像结果。
 官方给的测试效果图:
在这里插入图片描述
算法代码:https://github.com/richzhang/colorization

C++ 模型推理

1.这里使用的开发环境是win10,显卡RTX3080,cuda10.2,cudnn7.1,OpenCV4.5,NCNN,IDE 是Vs2019。
2.模型是从onnx转成ncnn的模型,转换方法可以参考ncnn的官网。
3.代码步骤就是加载模型后,输入一张灰度图像,模型给图像上色,输出一张彩色图像。
在这里插入图片描述

4.C++源码

#pragma once
#include <ncnn/net.h>
#include <ncnn/layer.h>
#include <opencv2/opencv.hpp>


class Color
{
public:
	Color();
	~Color();

	int read_models(std::string param_path, 
		std::string model_path, bool use_gpu);
	int image_color(cv::Mat& cv_src, cv::Mat& cv_dst);

private:
	ncnn::Net net;
	int width = 256;
	int height = 256;
};

#include "Color.h"

class Sig17Slice : public ncnn::Layer
{
public:
    Sig17Slice()
    {
        one_blob_only = true;
    }

    virtual int forward(const ncnn::Mat& bottom_blob, ncnn::Mat& top_blob, const ncnn::Option& opt) const
    {
        int w = bottom_blob.w;
        int h = bottom_blob.h;
        int channels = bottom_blob.c;

        int outw = w / 2;
        int outh = h / 2;
        //int outc = channels * 4;
        int outc = channels;

        top_blob.create(outw, outh, outc, 4u, 1, opt.blob_allocator);
        if (top_blob.empty())
            return -100;

#pragma omp parallel for num_threads(opt.num_threads)
        for (int p = 0; p < outc; p++)
        {
            const float* ptr = bottom_blob.channel(p % channels).row((p / channels) % 2) + ((p / channels) / 2);
            float* outptr = top_blob.channel(p);

            for (int i = 0; i < outh; i++)
            {
                for (int j = 0; j < outw; j++)
                {
                    *outptr = *ptr;

                    outptr += 1;
                    ptr += 2;
                }

                ptr += w;
            }
        }

        return 0;
    }
};

DEFINE_LAYER_CREATOR(Sig17Slice)

Color::Color()
{
}

Color::~Color()
{
}

int Color::read_models(std::string param_path, 
	std::string model_path, bool use_gpu)
{
    net.register_custom_layer("Sig17Slice", Sig17Slice_layer_creator);

	bool has_gpu = false;

#if NCNN_VULKAN
	ncnn::create_gpu_instance();
	has_gpu = ncnn::get_gpu_count() > 0;
#endif

	bool to_use_gpu = has_gpu && use_gpu;
	net.opt.use_vulkan_compute = to_use_gpu;

	int rp = net.load_param(param_path.c_str());

	int rb = net.load_model(model_path.c_str());

	if (rp < 0 || rb < 0)
	{
		return 1;
	}
	return 0;
}


int Color::image_color(cv::Mat& cv_src, cv::Mat& cv_dst)
{
    cv::Mat cv_base, cv_lab, cv_channel, cv_input;
    cv_base = cv_src.clone();

    cv_base.convertTo(cv_base, CV_32F, 1.0 / 255);

    cvtColor(cv_base, cv_lab, cv::COLOR_BGR2Lab);

    cv::extractChannel(cv_lab, cv_channel, 0);

    resize(cv_channel, cv_input, cv::Size(width, height));

    ncnn::Mat in(cv_input.cols, cv_input.rows, 1, (void*)cv_input.data);
    in = in.clone();


    ncnn::Extractor ex = net.create_extractor();
    ex.input("input", in);
    ncnn::Mat out;
    ex.extract("out_ab", out);

    cv::Mat colored_LAB(out.h, out.w, CV_32FC2);
    memcpy((uchar*)colored_LAB.data, out.data, 
        out.w * out.h * 2 * sizeof(float));

    //get separsted LAB channels a&b
    cv::Mat a(out.h, out.w, CV_32F, (float*)out.data);
    cv::Mat b(out.h, out.w, CV_32F, (float*)out.data + out.w * out.h);

    //Resize a, b channels to origina image size
    cv::resize(a, a, cv_base.size());
    cv::resize(b, b, cv_base.size());

    cv::Mat chn[] = { cv_channel, a, b };
    cv::merge(chn, 3, cv_lab);
    cvtColor(cv_lab, cv_dst, cv::COLOR_Lab2BGR);
    cv_dst.convertTo(cv_dst, CV_8UC3, 255);
    return 0;
}

5.运行结果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

源码配置

1.源码地址:https://download.csdn.net/download/matt45m/87374018
2.配置运行环境:
在这里插入图片描述
3.配置包含库:
在这里插入图片描述
4.配置lib路径:
在这里插入图片描述
4.添加链接:
在这里插入图片描述
这个里添加的工程目录下lib下的所的.lib的名字。

GenericCodeGen.lib
glslang.lib
MachineIndependent.lib
ncnn.lib
OGLCompiler.lib
opencv_world450.lib
OSDependent.lib
SPIRV.lib
VkLayer_utils.lib
vulkan-1.lib

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/149766.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Gradle学习笔记01

一、Gradle视频介绍新一代构建工具Gradle&#xff0c;提到项目自动化构建工具&#xff0c;首先提到的是Maven。现在谈谈Gradle与Maven之间的差异&#xff1a;同样作为项目自动化构建工具&#xff0c;Maven更侧重于项目jar包的管理&#xff0c;而Gradle侧重于项目的构建&#xf…

卷积层、卷积层里的填充和步幅

多层感知机正式总结卷积层之前&#xff0c;先把上次多层感知机落下的一点内容补一补。几个概念&#xff1a;训练数据集&#xff1a;训练模型参数。验证数据集&#xff1a;选择模型超参数。训练误差&#xff1a;模型在训练数据上的误差。泛化误差&#xff1a;模型在新数据上的误…

Linux常用命令——lftp命令

在线Linux命令查询工具 lftp 优秀的文件客户端程序 补充说明 lftp命令是一款优秀的文件客户端程序&#xff0c;它支持ftp、SETP、HTTP和FTPs等多种文件传输协议。lftp支持tab自动补全&#xff0c;记不得命令双击tab键&#xff0c;就可以看到可能的选项了。 语法 lftp(选项…

基于PCAP搭建软HUB实现物联网在线调试

完整工程可从以下地址签出&#xff1a; https://gitcode.net/coloreaglestdio/pcaphub.git 1.需求场景 在调试嵌入式物联设备时&#xff0c;尤其是在多个以太网物联设备交错通信的情况下&#xff0c;很难通过在捉襟见肘的嵌入式系统上进行数据记录与调试。如果设备连接的是一…

基于Kintex-7 FPGA的核心板电路设计

1. 引言Field Programmable GateArray&#xff08;简称&#xff0c;FPGA&#xff09;于1985年由XILINX创始人之一Ross Freeman发明&#xff0c;第一颗FPGA芯片XC2064为XILINX所发明&#xff0c;FPGA一经发明&#xff0c;后续的发展速度之快&#xff0c;超出大多数人的想象&…

系分 - 案例分析 - 需求获取

个人总结&#xff0c;仅供参考&#xff0c;欢迎加好友一起讨论 文章目录系分 - 案例分析 - 需求获取需求获取方法典型例题题目描述参考答案系分 - 案例分析 - 需求获取 需求获取方法 用户访谈 工作内容要点准备访谈步骤&#xff1a;1 确定访谈目的。2 确定访谈哪些用户。3 准…

PHP 文件上传

通过 PHP&#xff0c;可以把文件上传到服务器。 本章节实例在 test 项目下完成&#xff0c;目录结构为&#xff1a; test |-----upload # 文件上传的目录 |-----form.html # 表单文件 |-----upload_file.php # php 上传代码 源码下载 创建一个文件上…

获取Git权限的三种方式

获取Git权限的三种方式写在最前1. HTTPS配合用户名和密码访问Git1.1 获取当前项目的用户和密码1.2 通过临时用户获取Git权限2. HTTPS配合token访问Git2.1 创建token2.2 HTTPS配合token获取Git权限3. SSH访问Git3.1 生成SSH公钥和私钥3.2 使用SSH获取Git权限写在最前 本文以为Az…

力扣(LeetCode)375. 猜数字大小 II(2023.01.08)

我们正在玩一个猜数游戏&#xff0c;游戏规则如下&#xff1a; 我从 1 到 n 之间选择一个数字。 你来猜我选了哪个数字。 如果你猜到正确的数字&#xff0c;就会 赢得游戏 。 如果你猜错了&#xff0c;那么我会告诉你&#xff0c;我选的数字比你的 更大或者更小 &#xff0c;并…

接口测试——postman和Jemter

接口测试——postman和Jemterpostmanpostman工作原理postman入门postman的基础用法postman的高级用法使用postman管理测试用例批量执行测试用例postman断言环境变量和全局变量postman关联postman请求前置脚本postman参数化及生成测试报告参数化与数据驱动postman生成测试报告je…

(十五)内部类简述

目录 1.概述: 2.内部类之一:静态内部类 3.内部类之二:成员内部类 4.内部类之三:局部内部类 5.内部类之四:匿名内部类 1.概述: 内部类就是定义在一个类里面的类&#xff0c;里面的类可以理解成(寄生)。 2.内部类的使用场景、作用&#xff1a; ①当一个事务的内部&#xff0c;还…

GIT zip下载和clone下载的代码不一致?

问题场景 今天我在下载公司项目的时候遇到了一个问题&#xff0c;我选择了一个分支a&#xff0c;通过下载zip的代码发现是全的&#xff0c;而我通过clone的时候发现显示的是master上的代码 原因 其实是clone下载下来了&#xff0c;但是我idea中分支打开时默认选择的是master分支…

Compose 动画入门 (二) : 为什么animateDpAsState要用val ? MutableState和State有什么区别 ?

1. 前言 我们首先来实现一个Compose的动画(animateDpAsState) var big by remember {mutableStateOf(false) } val size by animateDpAsState(if (big) 100.dp else 50.dp)Box(Modifier.size(size).background(Color.Blue).clickable {big !big}) {}运行程序&#xff0c;来看…

第56篇-利用JSRpc分析某尾波的登录参数【2023-01-09】

声明:该专栏涉及的所有案例均为学习使用,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!如有侵权,请私信联系本人删帖! 文章目录 一、前言二、JsRpc的基本使用1.准备工作2.简单使用三、利用JSRpc分析尾波的登录参数1.网站分析2.构建rpc一、前言 以前使…

LabVIEW控制前面板对象

LabVIEW控制前面板对象控件引用句柄在引用句柄和经典引用句柄选板上&#xff0c;它可将前面板对象的引用传输给其它VI。右键单击前面板对象&#xff0c;从快捷菜单中选择创建引用&#xff0c;可建立一个VI服务器引用。而且&#xff0c;也可在程序框图上的VI服务器常量中找到前面…

2023年01月IDE流行度最新排名

点击查看最新IDE流行度最新排名&#xff08;每月更新&#xff09; 2023年01月IDE流行度最新排名 顶级IDE排名是通过分析在谷歌上搜索IDE下载页面的频率而创建的 一个IDE被搜索的次数越多&#xff0c;这个IDE就被认为越受欢迎。原始数据来自谷歌Trends 如果您相信集体智慧&am…

高性能分布式缓存Redis-第一篇章

高性能分布式缓存Redis-第一篇章一、缓存发展史&缓存分类1.1、大型网站中缓存的使用1.2、常见缓存的分类1.3、分布式缓存选型方案对比二、Redis概述&安装配置2.1、概述2.2、安装&配置三、数据类型选择&应用场景3.1、Redis的Key的设计规范3.1.1、key名设计3.1.2…

Linux中常用命令(初学整理附实例和自己的理解)

目录 00.tree命令 01. ls 指令 02. pwd命令 03. cd 指令 04. touch指令 05.mkdir指令 06.rmdir指令 && rm 指令 07.man指令 08.热键tab键 09.nano 10.stat 11.cp指令 12.mv指令 13. cat 14.more指令 15.less指令 16.head指令 17.tail指令 18.wc 19.echo 20.…

运营商云从ATH虎口夺食?

配图来自Canva可画 如今在云计算领域&#xff0c;国内市场与国际市场的分化越来越显著&#xff0c;国内市场也在走出与国际市场不同的路径&#xff0c;而其中最大的变量则是来自三大运营商的进场与冲击。 以天翼云、联通云以及移动云为代表&#xff0c;国内通讯运营商的云品牌…

挑战杯课外学术参赛作品—AI合约问卷调查系统

大学生课外学术科技作品竞赛 1.作品概述 1.1作品选题背景和意义 随着互联网技术的发展以及大数据、人工智能等新科技时代的来临&#xff0c;我国高校教育改革、高校人才培养也面临着新的机遇与挑战。一方面&#xff0c;为了实现国家战略、支撑快速发展的新经济&#xff0c;需…