写在前面:2020年12月-2021年5月搞了一阵,发现老师期望过高,却没有明确指导方向,纯是自己瞎碰壁,搞不明白,改行了,学前端了,现在是2022年1月,今年毕业就入职
1 配置环境
2 CUDA配置与测试
#include<opencv2/opencv.hpp>
#include<opencv2/cudaimgproc.hpp>
#include<iostream>
using namespace cv;
using namespace cv::cuda;
using namespace std;
int main(int argc, char **argv) {
cuda::printCudaDeviceInfo(cuda::getDevice());
int count = getCudaEnabledDeviceCount();
printf("device count:%d\n", count);
return 0;
}
3 第一个程序
int main(int argc, char **argv) {
Mat image_host = imread("lena.jpg");//CPU的内存对象
imshow("input", image_host);
//版本1.
//GpuMat image_device(image_host);//GPU的内存对象
//版本2.
GpuMat image_device;
image_device.upload(image_host);
GpuMat gray_device;
cuda::cvtColor(image_device, gray_device, COLOR_BGR2GRAY);//cuda加速的cvt版本
Mat gray_host;
gray_device.download(gray_host);
imshow("gray", gray_host);//注意:imshow显示不了GpuMat的对象
waitKey(0);
return 0;
}
4 GpuMat对象操作:算术与位运算
GpuMat与Mat的数据交换
-
cuda内存对象GpuMat
-
GpuMat与Mat的数据交换:通过upload,download进行
-
性能开销:频繁的GPU数据上传或下载都会耗时,最好只发生一次。
-
GpuMat对象有release方法,用完要及时释放。
简单的像素操作
int main(int argc, char **argv) {
Mat src1_host = imread("WindowsLogo.jpg");
Mat src2_host = imread("LinuxLogo.jpg");
//imshow("src1", src1_host);
//imshow("src2", src2_host);
//GPU对象
GpuMat src1_device, src2_device, dst_device;
src1_device.upload(src1_host);
src2_device.upload(src2_host);
cuda::add(src1_device, src2_device,dst_device);
//cuda::subtract(src1_device, src2_device, dst_device);
//cuda::multiply(src1_device, src2_device, dst_device);
Mat res;
dst_device.download(res);
//imshow("res", res);
//加减
//基于权重的融合
Mat src_host = imread("lena.jpg");
GpuMat src;
src.upload(src_host);
GpuMat black = GpuMat(src.size(),src.type());
cuda::addWeighted(src, 0.5, black, 0.5,127,dst_device);
cuda::bitwise_not(dst_device, dst_device);//位操作,每个位取反
dst_device.download(res);
imshow("Weighted add", res);
//颜色空间转换
GpuMat hsv, rgb, gray, YCrCb;
cuda::cvtColor(src, hsv, COLOR_BGR2HLS);
cuda::cvtColor(src, rgb, COLOR_BGR2RGB);
cuda::cvtColor(src, gray, COLOR_BGR2GRAY);
cuda::cvtColor(src, YCrCb, COLOR_BGR2YCrCb);
Mat hsv_host, rgb_host, gray_host, YCrCb_host;
hsv.download(hsv_host);
rgb.download(rgb_host);
gray.download(gray_host);
YCrCb.download(YCrCb_host);
waitKey(0);
return 0;
}
对于大量图像来说,cuda加速效果更明显
5 图像直方图&图像几何操作
int main(int argc, char **argv) {
Mat image_host = imread("lena.jpg");
imshow("input", image_host);
//直方图计算
GpuMat image(image_host);
vector<GpuMat> mv;
GpuMat hist, hsv;
cuda::split(image, mv);//分为三个通道
cuda::calcHist(mv[2],hist);//计算出来都是0-256,间隔是0-1
Mat hist_host;
hist.download(hist_host);
for (int i = 0; i < hist_host.cols; i++) {
int pv = hist_host.at<int>(0, i);
printf("total number: %d,of the pixel value: %d\n", pv, i);
}
//直方图均衡化
cuda::cvtColor(image, hsv, COLOR_BGR2HSV);
cuda::split(hsv, mv);
cuda::equalizeHist(mv[2], mv[2]);
cuda::merge(mv, hsv);
cuda::cvtColor(hsv, image, COLOR_HSV2BGR);
/*Mat result;
image.download(result);
imshow("eq-demo result",result);*/
//图像的几何计算
//resize and rotate
GpuMat dst;
cuda::resize(image, dst, Size(0, 0), 2, 2,INTER_CUBIC);
int cx = image.cols / 2;
int cy = image.rows / 2;
Mat M = getRotationMatrix2D(Point(cx, cy), 45, 1.0);
cuda::warpAffine(image, dst, M, image.size());
Mat result;
dst.download(result);
imshow("rotate result", result);
waitKey(0);
return 0;
}
注意:
对于直方图计算:
opencv的calcHist的Gpu版本每次只能计算图的一个通道(cpu版本可以计算多个通道)
直方图均衡化(灰度与彩色)
可以看出对比度变大。
图像几何变换
放大,缩小,旋转等
6 卷积操作 - 加速盒子模糊与高斯模糊
主要内容:
卷积模糊操作
- 盒子模糊
int main(int argc, char **argv) {
Mat image_host = imread("lena.jpg");
imshow("input", image_host);
GpuMat image, d_result3x3, d_result5x5, d_result9x9;
image.upload(image_host);
cuda::cvtColor(image, image, COLOR_BGR2BGRA);
//盒子模糊
//create box filter
auto filter_3x3 = cuda::createBoxFilter(image.type(), image.type(