首页 > 其他分享 >23、使用OpenCV和NCNN进行人物抠图并将背景设置成透明色

23、使用OpenCV和NCNN进行人物抠图并将背景设置成透明色

时间:2022-09-28 11:34:16浏览次数:81  
标签:Mat 23 comp fgr OpenCV NCNN alpha cv ncnn


基本思想:使用NCNN的example的生成白色背景的图片,然后在使用下面的代码将图片设置成四通道,且背景为透明颜色;

一、原图如下

23、使用OpenCV和NCNN进行人物抠图并将背景设置成透明色_ide

二、使用 例子生成纯白色的图片

ncnn代码:​​ncnn/examples at master · Tencent/ncnn · GitHub​

例子中的example/rvm.cpp代码

python代码:​​GitHub - PeterL1n/RobustVideoMatting: Robust Video Matting in PyTorch, TensorFlow, TensorFlow.js, ONNX, CoreML!​

原代码片段

 comp.at<cv::Vec3b>(i, j)[0] = fgr8U.at<cv::Vec3b>(i, j)[0] * alpha + (1 - alpha) * 155;
comp.at<cv::Vec3b>(i, j)[1] = fgr8U.at<cv::Vec3b>(i, j)[1] * alpha + (1 - alpha) * 255;
comp.at<cv::Vec3b>(i, j)[2] = fgr8U.at<cv::Vec3b>(i, j)[2] * alpha + (1 - alpha) * 120;

修改代码(白色纯背景)

 comp.at<cv::Vec3b>(i, j)[0] = fgr8U.at<cv::Vec3b>(i, j)[0] * alpha + (1 - alpha) * 255;
comp.at<cv::Vec3b>(i, j)[1] = fgr8U.at<cv::Vec3b>(i, j)[1] * alpha + (1 - alpha) * 255;
comp.at<cv::Vec3b>(i, j)[2] = fgr8U.at<cv::Vec3b>(i, j)[2] * alpha + (1 - alpha) * 255;

代码还需要添加一行代码,否则图片生成和之前的高宽不一样~

 cv::resize(comp, comp,cv::Size(bgr.cols,bgr.rows), 0, 0, cv::INTER_LINEAR);

23、使用OpenCV和NCNN进行人物抠图并将背景设置成透明色_ubuntu_02

三、将背景设置成透明色,使用下面的代码处理一下 


#include<iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/imgproc/types_c.h"
using namespace cv;
using namespace std;


void toPng(cv::Mat &src, cv::Mat &dst, int mark)
{
cv::Mat cv_input = src.clone();
if (cv_input.channels() != 4)
{
cv::cvtColor(cv_input, dst, CV_BGR2BGRA);
}
else
{
return;
}
for (int y = 0; y < dst.rows; ++y)
{
for (int x = 0; x < dst.cols; ++x)
{
cv::Vec4b & pixel = dst.at<cv::Vec4b>(y, x);
if ((int)pixel[0] >= mark && (int)pixel[1] >= mark && (int)pixel[2] >=mark)
{
pixel[3] = 0;
}
}
}
}



int main()
{
Mat dst;
Mat grayImage = imread("b.jpg");
toPng(grayImage, dst, 255);
imwrite("dst.png",dst);

return 0;
}

为啥png图片保存呢?引用

1、jpg是有损压缩格式,png是无损压缩格式。jpg是jpeg的简称,是目前网络上最为流行的图片格式,jpg格式的图片可以将图像文件压缩到最小格式,png全称为Portable Network Graphics,翻译过来就是便携式网络图形,它是一种无损压缩的图片形格式。jpg格式的图片能在高度压缩率的同时,可以展现十分丰富生动的图像,但是随着压缩比的增大,图片的品质会逐渐降低的。而png图片的特性就是体积小,节约空间,与jpg图片相比,png图片是无损压缩,在不损失图片数据的情况下,可以快速的获取自己想要的图片,而且图片的质量并不会下降。
2、jpg图像没有透明的背景,而png图像可以保留透明的背景。
3、png格式的图片可以编辑,但是jpg格式的图片则不可更改。png格式的图片可以编辑,比如图片中的字体,线条等,可以通过ps等软件更改。但是jpg格式的图片则不可更改。png与jpg图片相比png格式的图片更大。
4、png与jpg图片相比,png格式的图片更大。

结果图片

23、使用OpenCV和NCNN进行人物抠图并将背景设置成透明色_ubuntu_03

 用ps软件看上图更明显  ​​【在线PS软件】在线PS图片(照片)处理工具_在线制作编辑图片ps精简版​

23、使用OpenCV和NCNN进行人物抠图并将背景设置成透明色_#include_04

ncnn中的example源码 (改了一点点)

#include "ncnn/net.h"
#if defined(USE_NCNN_SIMPLEOCV)
#include "simpleocv.h"
#else
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#endif
#include <stdlib.h>
#include <float.h>
#include <stdio.h>
#include <vector>
#include <opencv2/imgproc/types_c.h>
#include<iostream>
using namespace std;
void toPng(cv::Mat& src, cv::Mat& dst, int mark)
{
cv::Mat cv_input = src.clone();
if (cv_input.channels() != 4)
{
cv::cvtColor(cv_input, dst, CV_BGR2BGRA);
}
else
{
return;
}
for (int y = 0; y < dst.rows; ++y)
{
for (int x = 0; x < dst.cols; ++x)
{
cv::Vec4b& pixel = dst.at<cv::Vec4b>(y, x);
// std::cout <<"pixel[0]= "<< pixel[0] << "pixel[1]= " << pixel[1] << "pixel[2]= " << pixel[2] << std::endl;
if (pixel[0] == mark && pixel[1] == mark && pixel[2] == mark)
{
pixel[3] = 0;
}
}
}
}


static void draw_objects(const cv::Mat& bgr, const cv::Mat& fgr, const cv::Mat& pha)
{
cv::Mat fgr8U;
fgr.convertTo(fgr8U, CV_8UC3, 255.0, 0);
cv::Mat pha8U;
pha.convertTo(pha8U, CV_8UC1, 255.0, 0);

cv::Mat comp;
cv::resize(bgr, comp, pha.size(), 0, 0, 1);
for (int i = 0; i < pha8U.rows; i++)
{
for (int j = 0; j < pha8U.cols; j++)
{
uchar data = pha8U.at<uchar>(i, j);
float alpha = (float)data / 255;
comp.at<cv::Vec3b>(i, j)[0] = fgr8U.at<cv::Vec3b>(i, j)[0] * alpha + (1 - alpha) * 255;//155
comp.at<cv::Vec3b>(i, j)[1] = fgr8U.at<cv::Vec3b>(i, j)[1] * alpha + (1 - alpha) * 255;//255
comp.at<cv::Vec3b>(i, j)[2] = fgr8U.at<cv::Vec3b>(i, j)[2] * alpha + (1 - alpha) * 255;//120
// std::cout <<(int)comp.at<cv::Vec3b>(i, j)[0] << " " << (int)comp.at<cv::Vec3b>(i, j)[1] <<" "<<(int)comp.at<cv::Vec3b>(i, j)[2] << std::endl;
}
}

// cv::imshow("pha", pha8U);
//cv::imshow("fgr", fgr8U);
//cv::Mat img1_t1(comp, cv::Rect(0, 0, comp.cols, comp.rows));
// toPng(comp, img1_t1, 0);
// cv::imshow("comp", comp);



cv::Mat img_alpha_0;

//
cv::resize(comp, comp,cv::Size(bgr.cols,bgr.rows), 0, 0, cv::INTER_LINEAR);
toPng(comp, img_alpha_0, 255);

imwrite("F:\\boost\\b.jpg", img_alpha_0);
cv::waitKey(0);
}
static int detect_rvm(const cv::Mat& bgr, cv::Mat& pha, cv::Mat& fgr)
{
const float downsample_ratio = 0.5f;
const int target_width = 512;
const int target_height = 512;

ncnn::Net net;
net.opt.use_vulkan_compute = false;
//original pretrained model from https://github.com/PeterL1n/RobustVideoMatting
//ncnn model https://pan.baidu.com/s/11iEY2RGfzWFtce8ue7T3JQ password: d9t6
net.load_param("G:\\rvm_ncnn_models\\rvm_512.param");
net.load_model("G:\\rvm_ncnn_models\\rvm_512.bin");

//if you use another input size,pleaze change input shape
ncnn::Mat r1i = ncnn::Mat(128, 128, 16);
ncnn::Mat r2i = ncnn::Mat(64, 64, 20);
ncnn::Mat r3i = ncnn::Mat(32, 32, 40);
ncnn::Mat r4i = ncnn::Mat(16, 16, 64);
r1i.fill(0.0f);
r2i.fill(0.0f);
r3i.fill(0.0f);
r4i.fill(0.0f);

ncnn::Extractor ex = net.create_extractor();
const float mean_vals1[3] = { 123.675f, 116.28f, 103.53f };
const float norm_vals1[3] = { 0.01712475f, 0.0175f, 0.01742919f };
const float mean_vals2[3] = { 0, 0, 0 };
const float norm_vals2[3] = { 1 / 255.0, 1 / 255.0, 1 / 255.0 };
ncnn::Mat ncnn_in2 = ncnn::Mat::from_pixels_resize(bgr.data, ncnn::Mat::PIXEL_BGR2RGB, bgr.cols, bgr.rows, target_width, target_height);
ncnn::Mat ncnn_in1 = ncnn::Mat::from_pixels_resize(bgr.data, ncnn::Mat::PIXEL_BGR2RGB, bgr.cols, bgr.rows, target_width * downsample_ratio, target_height * downsample_ratio);

ncnn_in1.substract_mean_normalize(mean_vals1, norm_vals1);
ncnn_in2.substract_mean_normalize(mean_vals2, norm_vals2);

ex.input("src1", ncnn_in1);
ex.input("src2", ncnn_in2);
ex.input("r1i", r1i);
ex.input("r2i", r2i);
ex.input("r3i", r3i);
ex.input("r4i", r4i);

//if use video matting,these output will be input of next infer
ex.extract("r4o", r4i);
ex.extract("r3o", r3i);
ex.extract("r2o", r2i);
ex.extract("r1o", r1i);

ncnn::Mat pha_;
ex.extract("pha", pha_);
ncnn::Mat fgr_;
ex.extract("fgr", fgr_);

cv::Mat cv_pha = cv::Mat(pha_.h, pha_.w, CV_32FC1, (float*)pha_.data);
cv::Mat cv_fgr = cv::Mat(fgr_.h, fgr_.w, CV_32FC3);
float* fgr_data = (float*)fgr_.data;
for (int i = 0; i < fgr_.h; i++)
{
for (int j = 0; j < fgr_.w; j++)
{
cv_fgr.at<cv::Vec3f>(i, j)[2] = fgr_data[0 * fgr_.h * fgr_.w + i * fgr_.w + j];
cv_fgr.at<cv::Vec3f>(i, j)[1] = fgr_data[1 * fgr_.h * fgr_.w + i * fgr_.w + j];
cv_fgr.at<cv::Vec3f>(i, j)[0] = fgr_data[2 * fgr_.h * fgr_.w + i * fgr_.w + j];
}
}

cv_pha.copyTo(pha);
cv_fgr.copyTo(fgr);

return 0;
}
int main(int argc, char** argv)
{


cv::Mat m = cv::imread("F:\\boost\\a.jpg");
if (m.empty())
{

return -1;
}

cv::Mat fgr, pha;
detect_rvm(m, pha, fgr);
draw_objects(m, fgr, pha);

return 0;
}

标签:Mat,23,comp,fgr,OpenCV,NCNN,alpha,cv,ncnn
From: https://blog.51cto.com/u_12504263/5719078

相关文章

  • 20、NanoDet训练、测试 以及使用ncnn部署Jetson Nano 进行目标检测和串口数据转发
    基本思想:最近想尝试一下nano上部署nanodet,于是记录一下训练过程,手中有一份labelme标注的数据集,于是开始了一波操作~首先进行划分数据集分为训练集和验证集 31、TensorFlow......
  • USB-RS232转换器芯片GP232RL兼容FT232
    芯片介绍GP232RL是一款高度集成的USB到UART桥接控制器,提供了一种简单的解决方案,可以使用最少的元器件和PCB空间,将RS232接口转换为USB接口。GP232R包括一个USB2.0全速功能......
  • 19、Opencv4.4的仿射矩阵处理
    基本思想:深入学习一下仿射矩阵的使用和分解环境window10+Mingw32+Opencv4.4.0+Eigen这里仅说明一下Eigen库的导入方法,首先去Eigen官网下载Eigen源码,解压导入Clion工程中,修......
  • 14、OpenCV4.4进行区域的相交比计算
    基本思想:进行两个区域的相交比计算  #include<opencv2/opencv.hpp>#include<opencv2/core/core.hpp>#include<opencv2/highgui/highgui.hpp>#include<iostream>using......
  • 17、OpenCV灰度翻转\增强\压缩\伽马变化
    基本思想:基本原理参考OpenCV手册,此处只记录一下如何使用;#include<opencv2/opencv.hpp>#include<iostream>#include<vector>usingnamespacestd;usingnamespacecv;intma......
  • 4、openCV 图像像素
    #-*-coding:utf-8-*-importcv2,matplotlibimportnumpyasnpimportmatplotlib.pyplotaspltcols=640rows=480image=cv2.imread('2.jpg')printimage.shapewi......
  • 3、openCV 平均图像的颜色
    #-*-coding:utf-8-*-importcv2,matplotlibimportnumpyasnpimportmatplotlib.pyplotaspltpixel=cv2.imread('2.jpg')print'pixel=',pixelaverage_img=np.aver......
  • 13、OpenCV4.4 仿射变换
    Parameters:src–Coordinatesoftriangleverticesinthesourceimage.dst–Coordinatesofthecorrespondingtriangleverticesinthedestinationimage.Thefunc......
  • 9、OpenCV4.4 色彩抽出
    色彩的空间变换#-*-coding:utf-8-*-importcv2importnumpyasnporiginal=cv2.imread('1.jpg',1)img=original.copy()#副本dst=np.zeros(img.shape,np.uint8)#......
  • P3238 [HNOI2014]道路堵塞
    P3238HNOI2014道路堵塞点击查看代码#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<utility>#include<array>#incl......