本章我们继续使用OpenCV-C++版本在CUDA下的编程应用,主要使用双边模糊,对图像进行美颜细化。
1、高斯双边模糊
int main(int argc, char** argv)
{
Mat image = imread("F:/test/face_image.jpg");
imshow("input image", image);
cuda::GpuMat image_gpu,dst;
image_gpu.upload(image);
//高斯双边模糊
cuda::bilateralFilter(image_gpu, dst, 0, 100, 15, 4);
Mat result;
dst.download(result);
imshow("result", result);
waitKey(0);
return 0;
}
原图:
模糊处理后的结果:
看上去效果还不错,脸上的坑坑洼洼都被去掉了。
当然,除了图片以外,还可以使用视频或摄像头:
void video_test_gpu()
{
VideoCapture cap(0);
Mat frame,result;
cuda::GpuMat frame_gpu,dst_gpu;
while (true)
{
double t1 = getTickCount();
cap.read(frame);
frame_gpu.upload(frame);
cuda::bilateralFilter(frame_gpu, dst_gpu, 0, 50, 10, 4);
dst_gpu.download(result);
double fps = getTickFrequency()/(getTickCount() - t1);
putText(result, format("FPS:%.2f", fps), Point(50, 50), FONT_HERSHEY_PLAIN, 1.5, Scalar(0, 0, 255), 2, 8);
imshow("video-result", result);
if (char(waitKey(1)) == 27)
break;
}
return;
}
2、均值漂移滤波
均值漂移滤波在OpenCV CPU版本中的实时速度非常非常慢。那么通过GPU加速之后,速度会是怎样的呢?
void image_meanshift_gpu()
{
Mat image = imread("F:/test/face_image.jpg");
imshow("input image", image);
cuda::GpuMat image_gpu, dst;
image_gpu.upload(image);
double t1 = getTickCount();
cuda::cvtColor(image_gpu, image_gpu, COLOR_BGR2BGRA);//转为4通道
//均值漂移滤波
cuda::meanShiftFiltering(image_gpu, dst, 5, 80);
double fps = getTickFrequency() / (getTickCount() - t1);
Mat result;
dst.download(result);
putText(result, format("FPS:%.2f", fps), Point(50, 50), FONT_HERSHEY_PLAIN, 1.5, Scalar(0, 0, 255), 2, 8);
imshow("meanShift result", result);
video_test_gpu(); //GPU meanShift
return;
}
结果:
可以看到,FPS达到了200多帧,快到不行。实际上,在做应用的时候,可以先找出人脸区域,然后在进行滤波操作,这样更好。
附上所有代码:
#include<opencv2/opencv.hpp>
#include<opencv2/cudaimgproc.hpp>
#include<iostream>
using namespace std;
using namespace cv;
void video_test_gpu();
void image_meanshift_gpu();
int main(int argc, char** argv)
{
Mat image = imread("F:/test/face_image.jpg");
imshow("input image", image);
cuda::GpuMat image_gpu,dst;
image_gpu.upload(image);
//高斯双边模糊
cuda::bilateralFilter(image_gpu, dst, 0, 100, 15, 4);
Mat result;
dst.download(result);
imshow("result", result);
//video_test_gpu(); //GPU-双边滤波视频
image_meanshift_gpu();//GPU-均值漂移
waitKey(0);
destroyAllWindows();
return 0;
}
void video_test_gpu()
{
VideoCapture cap(0);
Mat frame,result;
cuda::GpuMat frame_gpu,dst_gpu;
while (true)
{
double t1 = getTickCount();
cap.read(frame);
frame_gpu.upload(frame);
cuda::bilateralFilter(frame_gpu, dst_gpu, 0, 50, 10, 4);
dst_gpu.download(result);
double fps = getTickFrequency()/(getTickCount() - t1);
putText(result, format("FPS:%.2f", fps), Point(50, 50), FONT_HERSHEY_PLAIN, 1.5, Scalar(0, 0, 255), 2, 8);
imshow("video-result", result);
if (char(waitKey(1)) == 27)
break;
}
return;
}
void image_meanshift_gpu()
{
Mat image = imread("F:/test/face_image.jpg");
imshow("input image", image);
cuda::GpuMat image_gpu, dst;
image_gpu.upload(image);
double t1 = getTickCount();
cuda::cvtColor(image_gpu, image_gpu, COLOR_BGR2BGRA);//转为4通道,GPU只支持4通道
//均值漂移滤波
cuda::meanShiftFiltering(image_gpu, dst, 5, 80); //值越低,计算量越小
double fps = getTickFrequency() / (getTickCount() - t1);
Mat result;
dst.download(result);
putText(result, format("FPS:%.2f", fps), Point(50, 50), FONT_HERSHEY_PLAIN, 1.5, Scalar(0, 0, 255), 2, 8);
imshow("meanShift result", result);
video_test_gpu(); //GPU meanShift
return;
}