QT5+OpenCV磨皮效果
来源:互联网 发布:java判断字符串字符集 编辑:程序博客网 时间:2024/04/28 13:30
磨皮的详细内容请参考大神的博文:简单探讨可牛影像软件中具有肤质保留功能的磨皮算法及其实现细节。
根据上面文中所述,磨皮的主要公式为:Dest =(Src * (100 - Opacity) + (Src + 2 * GuassBlur(EPFFilter(Src) - Src + 128) - 256) * Opacity) /100
其中用到OpenCV的双边滤波:
以及OpenCV的高斯模糊:
将公式转换为OpenCV代码如下;其中src为原图;dst为输出图片;输入参数value1为磨皮程度,value2为细节程度;尽量保持分步处理,合并步骤可能会出错
根据上面文中所述,磨皮的主要公式为:Dest =(Src * (100 - Opacity) + (Src + 2 * GuassBlur(EPFFilter(Src) - Src + 128) - 256) * Opacity) /100
其中用到OpenCV的双边滤波:
bilateralFilter(InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace,int borderType=BORDER_DEFAULT );
以及OpenCV的高斯模糊:
void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT );注意ksize的宽和高必须是奇数
将公式转换为OpenCV代码如下;其中src为原图;dst为输出图片;输入参数value1为磨皮程度,value2为细节程度;尽量保持分步处理,合并步骤可能会出错
void buffing(int value1,int value2){ int dx = value1*5; //双边滤波参数之一 double fc = value1*12.5; //双边滤波参数之一 int p = 50;//透明度 Mat temp1,temp2,temp3,temp4; //双边滤波 bilateralFilter(src, temp1, dx, fc, fc); temp2 = (temp1 - src + 128); //高斯模糊 GaussianBlur(temp2, temp3, Size(2*value2 - 1, 2*value2 - 1), 0, 0); temp4 = src + 2*temp3 - 255; dst = ( src*(100-p) + temp4*p ) / 100;}
效果图
PS:磨皮加美白代码
- mainwindow.h
#ifndef MAINWINDOW_H#define MAINWINDOW_H#include <QMainWindow>#include<opencv2/core/core.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/highgui/highgui.hpp>#include <iostream>#include<QPixmap>using namespace std;using namespace cv;namespace Ui {class MainWindow;}class MainWindow : public QMainWindow{ Q_OBJECTpublic: explicit MainWindow(QWidget *parent = 0); ~MainWindow();private slots: void on_horizontalSlider_valueChanged(int value); void on_horizontalSlider_2_valueChanged(int value); void on_openButton_clicked(); void on_saveButton_clicked(); void on_horizontalSlider_3_valueChanged(int value);private: Ui::MainWindow *ui; Mat src,dst,result,white; void displayResult(Mat mat); int dx; double fc; QString fileName; int FMax(const int X, const int Y); int FMin(const int X, const int Y); //转换数组 double highlights_add[256], highlights_sub[256]; double midtones_add[256], midtones_sub[256]; double shadows_add[256], shadows_sub[256]; void BalanceColor(Mat& bitmap,int value);};#endif // MAINWINDOW_H
- mainwindow.cpp
#include "mainwindow.h"#include "ui_mainwindow.h"#include<QFileDialog>#include<QImage>#include<QDebug>MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow){ ui->setupUi(this); //初始化转换数组 for (int i = 0; i < 256; i++) { highlights_add[i] = shadows_sub[255 - i] = (1.075 - 1 / ((double) i / 16.0 + 1)); midtones_add[i] = midtones_sub[i] = 0.667 * (1 - (((double) i - 127.0) / 127.0)*(((double) i - 127.0) / 127.0)); shadows_add[i] = highlights_sub[i] = 0.667 * (1 - (((double) i - 127.0) / 127.0)*(((double) i - 127.0) / 127.0)); } dx = 0; //大小 fc = 0; //方差 ui->openButton->setStyleSheet("QPushButton{border: 3px solid grey;background:rgb(183,203,188);border-radius: 5px;}QPushButton:hover{border-color:rgb(183,203,188);}QPushButton:pressed{border-color:gray}"); ui->saveButton->setStyleSheet("QPushButton{border: 3px solid grey;background:rgb(183,203,188);border-radius: 5px;}QPushButton:hover{border-color:rgb(183,203,188);}QPushButton:pressed{border-color:gray}");}MainWindow::~MainWindow(){ delete ui;}//QLabel显示mat图像void MainWindow::displayResult(Mat mat){ Mat rgb; QImage img; if(mat.channels() == 3) // RGB image { cvtColor(mat,rgb,CV_BGR2RGB); img = QImage((const uchar*)(rgb.data), //(const unsigned char*) rgb.cols,rgb.rows, rgb.cols*rgb.channels(), //new add QImage::Format_RGB888); }else // gray image { img = QImage((const uchar*)(mat.data), mat.cols,mat.rows, mat.cols*mat.channels(), //new add QImage::Format_Indexed8); } ui->showLabel->setPixmap(QPixmap::fromImage(img));}void MainWindow::on_horizontalSlider_valueChanged(int value){ ui->dxLabel->setText(tr("%1").arg(value)); if(fileName.isEmpty()) return; dx = value*5; fc = value*12.5; //双边滤波 bilateralFilter(src,dst,dx,fc,fc); ui->horizontalSlider_2->setValue(1); ui->horizontalSlider_3->setValue(0); displayResult(dst); result = dst.clone(); white = dst.clone();}void MainWindow::on_horizontalSlider_2_valueChanged(int value){ ui->fcLabel->setText(tr("%1").arg(value)); if(fileName.isEmpty()) return; Mat temp1,temp2,temp3,temp4; ui->horizontalSlider_3->setValue(0); //Dest =(Src * (100 - Opacity) + (Src + 2 * GuassBlur(EPFFilter(Src) - Src + 128) - 256) * Opacity) /100 ; bilateralFilter(src,temp1,dx,fc,fc); temp2 = (temp1-src+128); GaussianBlur(temp2,temp3,Size((2*value-1),(2*value-1)),0,0); temp4 = src+2*temp3-255; int p = 50;//透明度 dst = (src*(100-p) + temp4*p)/100; displayResult(dst); result = dst.clone(); white = dst.clone();}void MainWindow::on_openButton_clicked(){ fileName = QFileDialog::getOpenFileName(this,tr("打开图片"),tr(".")); if(fileName.isEmpty()) return; src = imread(fileName.toStdString()); result = src.clone(); white = src.clone(); ui->showLabel->setPixmap(QPixmap(fileName)); ui->horizontalSlider->setValue(0); ui->horizontalSlider_2->setValue(1);}void MainWindow::on_saveButton_clicked(){ if(fileName.isEmpty()) return; QString saveName = QFileDialog::getSaveFileName(this,tr("保存文件"),tr("."),"JPEG(*.jpg);;PNG(*.png);;BMP(*.bmp)"); if(saveName.isEmpty()) return; imwrite(saveName.toStdString(),result);}void MainWindow::on_horizontalSlider_3_valueChanged(int value){ ui->whiteLabel->setText(tr("%1").arg(value)); if(fileName.isEmpty()) return; Mat temp = white.clone(); BalanceColor(temp,value*15); displayResult(temp); result = temp.clone();}int MainWindow::FMax(const int X, const int Y){ return (X < Y ? Y : X);}int MainWindow::FMin(const int X, const int Y){ return (Y < X ? Y : X);}void MainWindow::BalanceColor(Mat& bitmap,int value){ int red, green, blue; unsigned char r_lookup[256],g_lookup[256],b_lookup[256]; for (int i = 0; i < 256; i++) { red = i; green = i; blue = i; red += (int)( 0.0 * shadows_sub[red] + value * midtones_add[red] + 0.0 * highlights_sub[red]); red = FMax(0,FMin(0xFF,red)); green += (int)( 0.0 * shadows_sub[green] + value * midtones_add[green] + 0.0 * highlights_sub[green]); green = FMax(0,FMin(0xFF,green)); blue += (int)( 0.0 * shadows_sub[blue] + value * midtones_add[blue] + 0.0 * highlights_sub[blue]); blue = FMax(0,FMin(0xFF,blue)); r_lookup[i] = (unsigned char)red; g_lookup[i] = (unsigned char)green; b_lookup[i] = (unsigned char)blue; } for (int row = 0; row < bitmap.rows; row++) { for (int col = 0; col < bitmap.cols; col++) { bitmap.at<Vec3b>(row, col)[0] = b_lookup[bitmap.at<Vec3b>(row, col)[0]]; bitmap.at<Vec3b>(row, col)[1] = g_lookup[bitmap.at<Vec3b>(row, col)[1]]; bitmap.at<Vec3b>(row, col)[2] = r_lookup[bitmap.at<Vec3b>(row, col)[2]]; } }}
- main.cpp
#include "mainwindow.h"#include <QApplication>int main(int argc, char *argv[]){ QApplication a(argc, argv); MainWindow w; w.show(); return a.exec();}
1 0
- QT5+OpenCV磨皮效果
- QT5+OpenCV美白效果
- Qt5 for android + opencv
- Qt5 for android + opencv
- windows7 + Qt5 + opencv配置
- Qt5配置opencv注意事项
- Qt5 for android + opencv
- Qt5+OpenCV软件打包
- opencv+Qt5 知识点
- Opencv+ qt5.1 完美配置
- QT5.3 +opencv +vs2010 配置,
- QT5.4.0配置OpenCV环境
- QT5+OpenCV人脸识别
- Qt5+opencv程序打包发布
- QT5.5.1+VS2013+OpenGL+OpenCV
- VS2012-QT5-OPENCV环境搭建
- Qt5 OpenCV函数 imread()
- centos7 Qt5.9.1 使用opencv
- 智能称体脂称实现(基本原理解释篇)
- ViewPager Indicator的tab数据来自网络出现找不到viewPager的错误
- Linux C Socket编程原理及简单实例
- 浅谈Spring事务隔离级别
- 关于移动端清除下拉菜单的默认样式
- QT5+OpenCV磨皮效果
- android eclipse 混淆jar代码
- cocos2dx socket 通信
- 测量函数的运行时间
- 驱动中使用栈内存的问题
- Genymotion - 强大好用高性能的 Android 模拟器 (在电脑流畅运行APK安卓软件游戏的利器)
- Android 中dp,px,dpi以及sp的区别
- 网络中一些特殊的地址和地址范围
- 安卓开发-Activity中finish() onDestroy() 和System.exit()的区别