图像手工画效果【QT+OpenCV】

效果例如以下

【木雕】


【铅笔画】


【素描】


【实现工具】

QT+OpenCV

【源码】


【木雕】

void MainWindow::on_woodCarving_triggered()
{
    //木雕效果
    //假设当前点的像素值与临近随意一点的像素值大于阈值(这里设置为30),置白色。否则,置黑色
    Mat dst(srcImage.rows,srcImage.cols,CV_8UC1);
    Mat src;
    cvtColor(srcImage,src,CV_RGB2GRAY);
    for (int i=1; i<src.rows-1; i++)
    {

        uchar *current = src.ptr<uchar>(i);
        uchar *currentBefore = src.ptr<uchar>(i-1);
        uchar *currentNext = src.ptr<uchar>(i+1);
        //   uchar *currentNext = src.ptr<uchar>(i+1);
        uchar *dstLine = dst.ptr<uchar>(i);
        for (int j=1; j<src.cols-1; j++)
        {
            int a,b,c,d,e,f,g,h;
            a=abs(current[j]-currentBefore[(j-1)]);
            b=abs(current[j]-currentBefore[j]);
            c=abs(current[j]-currentBefore[(j+1)]);
            d=abs(current[j]-currentNext[(j-1)]);
            e=abs(current[j]-currentNext[(j)]);
            f=abs(current[j]-currentNext[(j+1)]);
            g=abs(current[j]-current[(j-1)]);
            h=abs(current[j]-current[(j+1)]);
            /*
            for(int m=-1;m<2;m++)
                for(int n=-1;n<2;n++)
                */
            /*
             *  //假设不先进行灰度处理,能够採用例如以下方式。对每个RGB分量进行处理。
            for(int k=0;k<3;k++)
            {
                sum+=abs(current[3*j+k]-currentBefore[3*(j-1)+k]);
                sum+=abs(current[3*j+k]-currentBefore[3*j+k]);
                sum+=abs(current[3*j+k]-currentBefore[3*(j+1)+k]);
                sum+=abs(current[3*j+k]-currentNext[3*(j-1)+k]);
                sum+=abs(current[3*j+k]-currentNext[3*(j)+k]);
                sum+=abs(current[3*j+k]-currentNext[3*(j+1)+k]);
                sum+=abs(current[3*j+k]-current[3*(j-1)+k]);
                sum+=abs(current[3*j+k]-current[3*(j+1)+k]);
            }
            */
            if(a>30||b>30||c>30||d>30||e>30||f>30||g>30||h>30)
                dstLine[j]=255;
            else
                dstLine[j]=0;
        }
    }
    // dst.copyTo(dst);
    cv::Size    dsize=Size(ui->label2->width(),ui->label2->height());
    cv::resize(dst,dst,dsize);
    /*imshow("src",src);
      imshow("dst",dst);
      */
    //showLabel(dst,ui->label2);
    // imshow("dst",dst);
    img = QImage((const unsigned char*)(dst.data),dst.cols,dst.rows,dst.cols*dst.channels(), QImage::Format_Indexed8);
    //l.clear();
    ui->label2->clear();
    //img=  img.scaled(l.width(),l.height());
    // img=img.scaled(ui->label2->width(),ui->label2->height());
    //l.setPixmap(QPixmap::fromImage(img));
    ui->label2->setPixmap(QPixmap::fromImage(img));
}

【铅笔画】

void MainWindow::on_pencil_triggered()
{
    //铅笔画
    //假设当前点的像素值与临近随意一点的像素值大于阈值(这里设置为30)。置黑色。否则。置白色
    //这里和木雕是相反的操作。

Mat dst(srcImage.rows,srcImage.cols,CV_8UC1); Mat src; cvtColor(srcImage,src,CV_RGB2GRAY); for (int i=1; i<src.rows-1; i++) { uchar *current = src.ptr<uchar>(i); uchar *currentBefore = src.ptr<uchar>(i-1); uchar *currentNext = src.ptr<uchar>(i+1); // uchar *currentNext = srcImage.ptr<uchar>(i+1); uchar *dstLine = dst.ptr<uchar>(i); for (int j=1; j<src.cols-1; j++) { int a,b,c,d,e,f,g,h; a=abs(current[j]-currentBefore[(j-1)]); b=abs(current[j]-currentBefore[j]); c=abs(current[j]-currentBefore[(j+1)]); d=abs(current[j]-currentNext[(j-1)]); e=abs(current[j]-currentNext[(j)]); f=abs(current[j]-currentNext[(j+1)]); g=abs(current[j]-current[(j-1)]); h=abs(current[j]-current[(j+1)]); /* for(int m=-1;m<2;m++) for(int n=-1;n<2;n++) */ /* * //假设不先进行灰度处理。能够採用例如以下方式。

对每个RGB分量进行处理。 for(int k=0;k<3;k++) { sum+=abs(current[3*j+k]-currentBefore[3*(j-1)+k]); sum+=abs(current[3*j+k]-currentBefore[3*j+k]); sum+=abs(current[3*j+k]-currentBefore[3*(j+1)+k]); sum+=abs(current[3*j+k]-currentNext[3*(j-1)+k]); sum+=abs(current[3*j+k]-currentNext[3*(j)+k]); sum+=abs(current[3*j+k]-currentNext[3*(j+1)+k]); sum+=abs(current[3*j+k]-current[3*(j-1)+k]); sum+=abs(current[3*j+k]-current[3*(j+1)+k]); } */ if(a>30||b>30||c>30||d>30||e>30||f>30||g>30||h>30) dstLine[j]=0; else dstLine[j]=255; } } cv::Size dsize=Size(ui->label2->width(),ui->label2->height()); cv::resize(dst,dst,dsize); /*imshow("srcImage",srcImage); imshow("dstImage",dstImage); */ //showLabel(dstImage,ui->label2); // imshow("dstImage",dstImage); img = QImage((const unsigned char*)(dst.data),dst.cols,dst.rows,dst.cols*dst.channels(), QImage::Format_Indexed8); //l.clear(); ui->label2->clear(); //img= img.scaled(l.width(),l.height()); // img=img.scaled(ui->label2->width(),ui->label2->height()); //l.setPixmap(QPixmap::fromImage(img)); ui->label2->setPixmap(QPixmap::fromImage(img)); }


【素描】

void MainWindow::on_sketch_triggered()
{
    //素描
    Mat src;
    srcImage.copyTo(src);
    int width=src.cols;
    int heigh=src.rows;
    Mat gray0,gray1;
    cvtColor(src,gray0,CV_BGR2GRAY);   //灰度处理
    addWeighted(gray0,-1,NULL,0,255,gray1);    //反色
    //   threshold(gray0,gray1,128,255,THRESH_BINARY_INV);
    GaussianBlur(gray1,gray1,Size(11,11),0);   //高斯处理一下
    Mat dst(gray1.size(),CV_8UC1);
    for (int y=0; y<heigh; y++)
    {
        uchar* P0  = gray0.ptr<uchar>(y);
        uchar* P1  = gray1.ptr<uchar>(y);
        uchar* P  = dst.ptr<uchar>(y);
        for (int x=0; x<width; x++)
        {
            int tmp0=P0[x];
            int tmp1=P1[x];
            P[x] =(uchar) min((tmp0+(tmp0*tmp1)/(256-tmp1)),255);   //计算
        }
    }
    cv::Size dsize=Size(ui->label2->width(),ui->label2->height());
    cv::resize(dst,dstImage,dsize);
    //   cv::cvtColor(m,m,CV_BGR2RGB);
    img = QImage((const unsigned char*)(dstImage.data),dstImage.cols,dstImage.rows,dstImage.cols*dstImage.channels(), QImage::Format_Indexed8);
    //l.clear();
    ui->label2->clear();
    //img=  img.scaled(l.width(),l.height());
    // img=img.scaled(ui->label2->width(),ui->label2->height());
    //l.setPixmap(QPixmap::fromImage(img));
    ui->label2->setPixmap(QPixmap::fromImage(img));
    /*
    imshow("a",dst);
    waitKey();
*/
}

參考资料

1.http://www.douban.com/group/topic/28961821/

2.http://blog.csdn.net/column/details/stylizefliter.html

posted @ 2017-06-14 21:48  yangykaifa  阅读(271)  评论(0编辑  收藏  举报