效果如下
【木雕】
【铅笔画】
【素描】
【实现工具】
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/