opencv進階 ——(九)圖像處理之人臉修復祛馬賽克算法CodeFormer

算法簡介

CodeFormer是一種基于AI技術深度學習的人臉復原模型,由南洋理工大學和商湯科技聯合研究中心聯合開發,它能夠接收模糊或馬賽克圖像作為輸入,并生成更清晰的原始圖像。算法源碼地址:https://github.com/sczhou/CodeFormer

Face Restoration

Face Color Enhancement and Restoration

Face Inpainting

模型部署

????????如果想用C++進行模型推理部署,首先要把模型轉換成onnx,轉成onnx就可以使用onnxruntime c++庫進行部署,或者使用OpenCV的DNN也可以。

? ? ? ? 1、可在以下地址下載模型:https://github.com/sczhou/CodeFormer/releases/tag/v0.1.0

? ? ? ? 2、下載CodeFormer源碼,在工程目錄下添加onnx轉換python代碼

import torch
from basicsr.utils.registry import ARCH_REGISTRYif __name__ == '__main__':device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')net = ARCH_REGISTRY.get('CodeFormer')(dim_embd=512, codebook_size=1024, n_head=8, n_layers=9, connect_list=['32', '64', '128', '256']).to(device)# ckpt_path = 'weights/CodeFormer/codeformer.pth'ckpt_path = './codeformer.pth'checkpoint = torch.load(ckpt_path)['params_ema']net.load_state_dict(checkpoint)net.eval()input_tensor = torch.zeros((1, 3, 512, 512)).to(device)torch.onnx.export(net,  # 模型實例input_tensor,  # 輸入張量"./codeformer.onnx",  # 輸出的ONNX模型路徑export_params=True,  # 是否包含模型參數opset_version=11,  # ONNX操作集版本do_constant_folding=True,  # 是否進行常量折疊優化input_names=['input'],  # 輸入名稱output_names=['output'],  # 輸出名稱dynamic_axes={'input': {0: 'batch_size'}, 'output': {0: 'batch_size'}}  # 聲明動態軸)

? ? ? ? 3、采用onnxruntime加載模型,示例代碼如下

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <fstream>
#include <numeric>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
//#include <cuda_provider_factory.h>  ///nvidia-cuda加速
#include <onnxruntime_cxx_api.h>using namespace cv;
using namespace std;
using namespace Ort;class CodeFormer
{
public:CodeFormer(string modelpath);Mat detect(Mat cv_image);
private:void preprocess(Mat srcimg);vector<float> input_image_;vector<double> input2_tensor;int inpWidth;int inpHeight;int outWidth;int outHeight;float min_max[2] = { -1,1 };//存儲初始化獲得的可執行網絡Env env = Env(ORT_LOGGING_LEVEL_ERROR, "CodeFormer");Ort::Session *ort_session = nullptr;SessionOptions sessionOptions = SessionOptions();vector<char*> input_names;vector<char*> output_names;vector<vector<int64_t>> input_node_dims; // >=1 outputsvector<vector<int64_t>> output_node_dims; // >=1 outputs
};CodeFormer::CodeFormer(string model_path)
{//OrtStatus* status = OrtSessionOptionsAppendExecutionProvider_CUDA(sessionOptions, 0);  ///nvidia-cuda加速sessionOptions.SetGraphOptimizationLevel(ORT_ENABLE_BASIC);std::wstring widestr = std::wstring(model_path.begin(), model_path.end());   ///如果在windows系統就這么寫ort_session = new Session(env, widestr.c_str(), sessionOptions);   ///如果在windows系統就這么寫///ort_session = new Session(env, model_path.c_str(), sessionOptions);  ///如果在linux系統,就這么寫size_t numInputNodes = ort_session->GetInputCount();size_t numOutputNodes = ort_session->GetOutputCount();AllocatorWithDefaultOptions allocator;for (int i = 0; i < numInputNodes; i++){input_names.push_back(ort_session->GetInputName(i, allocator));Ort::TypeInfo input_type_info = ort_session->GetInputTypeInfo(i);auto input_tensor_info = input_type_info.GetTensorTypeAndShapeInfo();auto input_dims = input_tensor_info.GetShape();input_node_dims.push_back(input_dims);}for (int i = 0; i < numOutputNodes; i++){output_names.push_back(ort_session->GetOutputName(i, allocator));Ort::TypeInfo output_type_info = ort_session->GetOutputTypeInfo(i);auto output_tensor_info = output_type_info.GetTensorTypeAndShapeInfo();auto output_dims = output_tensor_info.GetShape();output_node_dims.push_back(output_dims);}this->inpHeight = input_node_dims[0][2];this->inpWidth = input_node_dims[0][3];this->outHeight = output_node_dims[0][2];this->outWidth = output_node_dims[0][3];input2_tensor.push_back(0.5);
}void CodeFormer::preprocess(Mat srcimg)
{Mat dstimg;cvtColor(srcimg, dstimg, COLOR_BGR2RGB);resize(dstimg, dstimg, Size(this->inpWidth, this->inpHeight), INTER_LINEAR);this->input_image_.resize(this->inpWidth * this->inpHeight * dstimg.channels());int k = 0;for (int c = 0; c < 3; c++){for (int i = 0; i < this->inpHeight; i++){for (int j = 0; j < this->inpWidth; j++){float pix = dstimg.ptr<uchar>(i)[j * 3 + c];this->input_image_[k] = (pix / 255.0 - 0.5) / 0.5;k++;}}}
}Mat CodeFormer::detect(Mat srcimg)
{int im_h = srcimg.rows;int im_w = srcimg.cols;this->preprocess(srcimg);array<int64_t, 4> input_shape_{ 1, 3, this->inpHeight, this->inpWidth };vector<int64_t> input2_shape_ = { 1 };auto allocator_info = MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU);vector<Value> ort_inputs;ort_inputs.push_back(Value::CreateTensor<float>(allocator_info, input_image_.data(), input_image_.size(), input_shape_.data(), input_shape_.size()));ort_inputs.push_back(Value::CreateTensor<double>(allocator_info, input2_tensor.data(), input2_tensor.size(), input2_shape_.data(), input2_shape_.size()));vector<Value> ort_outputs = ort_session->Run(RunOptions{ nullptr }, input_names.data(), ort_inputs.data(), ort_inputs.size(), output_names.data(), output_names.size());post_processfloat* pred = ort_outputs[0].GetTensorMutableData<float>();//Mat mask(outHeight, outWidth, CV_32FC3, pred); /經過試驗,直接這樣賦值,是不行的const unsigned int channel_step = outHeight * outWidth;vector<Mat> channel_mats;Mat rmat(outHeight, outWidth, CV_32FC1, pred); // RMat gmat(outHeight, outWidth, CV_32FC1, pred + channel_step); // GMat bmat(outHeight, outWidth, CV_32FC1, pred + 2 * channel_step); // Bchannel_mats.push_back(rmat);channel_mats.push_back(gmat);channel_mats.push_back(bmat);Mat mask;merge(channel_mats, mask); // CV_32FC3 allocated///不用for循環遍歷Mat里的每個像素值,實現numpy.clip函數mask.setTo(this->min_max[0], mask < this->min_max[0]);mask.setTo(this->min_max[1], mask > this->min_max[1]);   也可以用threshold函數,閾值類型THRESH_TOZERO_INVmask = (mask - this->min_max[0]) / (this->min_max[1] - this->min_max[0]);mask *= 255.0;mask.convertTo(mask, CV_8UC3);cvtColor(mask, mask, COLOR_BGR2RGB);return mask;
}int main()
{CodeFormer mynet("codeformer.onnx");string imgpath = "input.png";Mat srcimg = imread(imgpath);Mat dstimg = mynet.detect(srcimg);resize(dstimg, dstimg, Size(srcimg.cols, srcimg.rows), INTER_LINEAR);//imwrite("result.jpg", dstimg)namedWindow("srcimg", WINDOW_NORMAL);imshow("srcimg", srcimg);namedWindow("dstimg", WINDOW_NORMAL);imshow("dstimg", dstimg);waitKey(0);destroyAllWindows();
}

效果展示

面部恢復

面部色彩增強與恢復

面部修復

破舊照片修復效果

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/20791.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/20791.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/20791.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何快速找到 RCE

背景介紹 本文將分享國外白帽子在‘偵察’階段如何快速發現 RCE 漏洞的經歷。以Apache ActiveMQ 的 CVE-2023–46604 為特例&#xff0c;重點介紹如何發現類似此類的漏洞&#xff0c;讓我們開始吧。 快速發現過程 在‘偵察’階段&#xff0c;白帽小哥會保持每周更新一次目標…

1940java swing零售庫存管理系統myeclipse開發Mysql數據庫CS結構java編程

一、源碼特點 java swing 零售庫存管理系統 是一套完善的窗體設計系統&#xff0c;對理解SWING java 編程開發語言有幫助&#xff0c;系統具有完整的源代碼和數據庫&#xff0c;&#xff0c;系統主要采用C/S模式開發。 應用技術&#xff1a;javamysql 開發工具&#xff1a;…

適合技術小白學習的項目1863java在線視頻網站系統 Myeclipse開發mysql數據庫web結構java編程計算機網頁項目

一、源碼特點 java在線視頻網站系統 是一套完善的web設計系統&#xff0c;對理解JSP java編程開發語言有幫助采用了java設計&#xff0c;系統具有完整的源代碼和數據庫&#xff0c;系統采用web模式&#xff0c;系統主要采用B/S模式開發。 開發環境為TOMCAT7.0,Myeclipse8.5開發…

數據庫、數據表的基本操作

1.數據庫的基本操作 &#xff08;1&#xff09;創建數據庫 &#xff08;2&#xff09;刪除數據庫 &#xff08;3&#xff09;將數據庫的字符集修改為gbk gbk是漢字內碼擴展規范&#xff0c;是GB2312和GB13000的擴展&#xff0c;主要用于簡體中文。 &#xff08;4&#xff09;…

LabVIEW在高校電力電子實驗中的應用

概述&#xff1a;本文介紹了如何利用LabVIEW優化高校電力電子實驗&#xff0c;通過圖形化編程實現參數調節、實時數據監控與存儲&#xff0c;并與Simulink聯動&#xff0c;提高實驗效率和數據處理能力。 需求背景高校實驗室在進行電機拖動和電力電子實驗時&#xff0c;通常使用…

前端框架安全防范

前端框架安全防范 在現代Web開發中&#xff0c;前端框架如Angular和React已經成為構建復雜單頁面應用&#xff08;SPA&#xff09;的主流工具。然而&#xff0c;隨著應用復雜度的增加&#xff0c;安全問題也變得越來越重要。本文將介紹如何在使用Angular和React框架時&#xf…

Java中的synchronized關鍵字詳解

Java中的synchronized關鍵字詳解 1. 引言 在Java編程中&#xff0c;多線程是提高應用性能的重要手段之一。然而&#xff0c;多線程環境下共享資源的訪問控制成為必須面對的問題。synchronized關鍵字作為Java語言提供的一種同步機制&#xff0c;能夠有效地解決這一問題。本文將…

施耐德 BAS PLC 基本操作指南

CPU 型號 項目使用的 PLC 型號為&#xff1a;施耐德昆騰 Quantum 140 CPU 67160 P266 CPU &#xff0c;支持熱備冗余&#xff0c;內部存儲 1024K&#xff0c;支持 2 個 PCMCIA 擴展卡槽CPU 模塊自帶接口&#xff1a;MB 串口接口、MB 串口接口、USB 接口、以太網接口&#xff…

MATLAB算法實戰應用案例精講-【數模應用】聯合分析(附python和MATLAB代碼實現)

目錄 前言 算法原理 什么是聯合分析? 聯合分析的基本原理與步驟

【HarmonyOS】List組件多層對象嵌套ForEach渲染更新的處理

【HarmonyOS】List組件多層對象嵌套ForEach渲染更新的處理 問題背景&#xff1a; 在鴻蒙中UI更新渲染的機制&#xff0c;與傳統的Android IOS應用開發相比。開發會簡單許多&#xff0c;開發效率提升顯著。 一般傳統應用開發的流程處理分為三步&#xff1a;1.畫UI&#xff0c;…

TiDB-從0到1-分布式存儲

TiDB從0到1系列 TiDB-從0到1-體系結構TiDB-從0到1-分布式存儲TiDB-從0到1-分布式事務TiDB-從0到1-MVCC 一、TiDB-DML語句執行流程&#xff08;增刪改&#xff09; DML流程概要 1、協議驗證 用戶連接到TiDB Server后首先工作的是Protocol Layer模塊&#xff0c;該模塊會對用…

mysql表字段超過多少影響性能 mysql表多少效率會下降

一直有傳言說&#xff0c;MySQL 表的數據只要超過 2000 萬行&#xff0c;其性能就會下降。而本文作者用實驗分析證明&#xff1a;至少在 2023 年&#xff0c;這已不再是 MySQL 表的有效軟限制。 傳言 互聯網上有一則傳言說&#xff0c;我們應該避免單個 MySQL 表中的數據超過 …

內網滲透-在HTTP協議層面繞過WAF

進入正題&#xff0c;隨著安全意思增強&#xff0c;各企業對自己的網站也更加注重安全性。但很多web應用因為老舊&#xff0c;或貪圖方便想以最小代價保證應用安全&#xff0c;就只僅僅給服務器安裝waf。 本次從協議層面繞過waf實驗用sql注入演示&#xff0c;但不限于實際應用…

[數據集][目標檢測]輪胎檢測數據集VOC+YOLO格式439張1類別

數據集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路徑的txt文件&#xff0c;僅僅包含jpg圖片以及對應的VOC格式xml文件和yolo格式txt文件) 圖片數量(jpg文件個數)&#xff1a;439 標注數量(xml文件個數)&#xff1a;439 標注數量(txt文件個數)&#xff1a;439 標注類別…

mysql怎么部署雙機

MySQL的雙機部署是為了實現數據的高可用性和容錯性。以下是MySQL雙機熱備部署的基本步驟&#xff0c;我會盡量清晰地分點表示和歸納&#xff1a; 1. 環境準備 安裝MySQL&#xff1a;在兩臺服務器上分別安裝MySQL數據庫。確保版本兼容。 網絡配置&#xff1a;確保兩臺服務器之…

題目:判斷一個素數能被幾個9整除

題目&#xff1a;判斷一個素數能被幾個9整除 There is no nutrition in the blog content. After reading it, you will not only suffer from malnutrition, but also impotence. The blog content is all parallel goods. Those who are worried about being cheated should …

顛仆流離學二叉樹2 (Java篇)

本篇會加入個人的所謂魚式瘋言 ??????魚式瘋言:??????此瘋言非彼瘋言 而是理解過并總結出來通俗易懂的大白話, 小編會盡可能的在每個概念后插入魚式瘋言,幫助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能說的不是那么嚴謹.但小編初心是能讓更多人…

泛型知識匯總

演示代碼&#xff1a; package exercise;import java.util.Arrays;public class MyArrayList<E> {Object[] obj new Object[10];int size;public boolean add(E e) {obj[size] e;size;return true;}public E get(int index) {return (E) obj[index];}//沒有這個函數&a…

現代信號處理12_譜估計的4種方法(CSDN_20240602)

Slepian Spectral Estimator(1950) 做譜估計的目標是盡可能看清楚信號功率譜在某一個頻率上的情況&#xff0c;假設我們想了解零頻時的分布&#xff0c;最理想的情況是濾波器的傳遞函數H(ω) 是一個沖激函數&#xff0c;這樣就沒有旁瓣&#xff0c;也就沒有泄漏&#xff1b;其次…

【OpenHarmony】TypeScript 語法 ③ ( 條件語句 | if else 語句 | switch case 語句 )

文章目錄 一、條件語句1、if else 語句2、switch case 語句 參考文檔 : <HarmonyOS第一課>ArkTS開發語言介紹 一、條件語句 1、if else 語句 TypeScript 中的 if 語句 / if else 語句 用法 , 與 JavaScript 語言中的 if 語句 / if else 語句 語法 基本相同 ; if else 語…