QT5+OpenCV磨皮效果

来源:互联网 发布:java判断字符串字符集 编辑:程序博客网 时间:2024/04/28 13:30
磨皮的详细内容请参考大神的博文:简单探讨可牛影像软件中具有肤质保留功能的磨皮算法及其实现细节。


根据上面文中所述,磨皮的主要公式为: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
原创粉丝点击