├── 介绍.pdf ├── 优化结果.PNG ├── README ├── Sobel_1.cu ├── Sobel_4a.cu ├── Sobel_3.cu └── Sobel_4b.cu /介绍.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Seafood-SIMIT/Sobel_With_CUDA-optimization/HEAD/介绍.pdf -------------------------------------------------------------------------------- /优化结果.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Seafood-SIMIT/Sobel_With_CUDA-optimization/HEAD/优化结果.PNG -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | 系统说明: 2 | 本代码运行于CUDA、OPENCV环境下,未在Windows上执行过,不过代码没错误,同时在Linux 3 | 系统上需自行编写Makefile 4 | 命令如下: 5 | nvcc -g -o Sobel_1 Sobel_1.cu `pkg-config opencv --cflags --libs` 6 | 各文件说明: 7 | /************************************************************************** 8 | * 文件名:Sobel_1.cu 9 | * 作者: 孙霖(Seafood) 10 | * 说明: cudau作业之Sobel算子边缘检测第一版 11 | * 调整使用Cpu包、CPU对像素点进行操作、GPU使用1thread、1block对像素点进行操作 12 | ****************************************************************************/ 13 | 14 | /************************************************************************** 15 | * 文件名:Sobel_3.cu 16 | * 作者: 孙霖(Seafood) 17 | * 说明: cudau作业之Sobel算子边缘检测第三版 18 | * 使用多block多thread对GPU程序进行优化二维 19 | ****************************************************************************/ 20 | 21 | /************************************************************************** 22 | * 文件名:Sobel_4a.cu 23 | * 作者: 孙霖(Seafood) 24 | * 说明: cudau作业之Sobel算子边缘检测第四版 25 | * 将数组存入常量内存 26 | * 27 | ****************************************************************************/ 28 | 29 | /************************************************************************** 30 | * 文件名:Sobel_4b.cu 31 | * 作者: 孙霖(Seafood) 32 | * 说明: cudau作业之Sobel算子边缘检测第四版 33 | * 将数组存入纹理内存 34 | * 35 | ****************************************************************************/ 36 | 欢迎指正错误 37 | -------------------------------------------------------------------------------- /Sobel_1.cu: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * 文件名:Sobel_1.cu 3 | * 作者: 孙霖(SC19023100)(Seafood) 4 | * 说明: cudau作业之Sobel算子边缘检测第一版 5 | * 调整使用Cpu包、CPU对像素点进行操作、GPU使用1thread、1block对像素点进行操作 6 | ****************************************************************************/ 7 | //----------------------------头文件包含和空间声明------------------------------------ 8 | #include "cuda_runtime.h" 9 | #include "cuda.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | typedef unsigned char uchar; 16 | 17 | //命名空间 18 | using namespace std; 19 | using namespace cv; 20 | 21 | #define uchar unsigned char 22 | //----------------------------全局变量--------------------------------------------- 23 | Mat g_sobelGradient_X, g_sobelGradient_Y; //opencv包使用的全局变量 24 | Mat g_sobelAbsGradient_X, g_sobelAbsGradient_Y; //opencv包使用的全局变量 25 | int g_sobelKernelSize = 1; 26 | 27 | Mat dst_Cpu, g_gaussImage, g_grayImage, g_dstImage; //图像读取+高斯滤波 28 | 29 | int g_imgHeight, g_imgWidth; //图像的大小Size 30 | 31 | //变换矩阵 32 | 33 | /** 34 | *@author:Seafood 35 | *@name:sobelInCuda() 36 | *@return:void 37 | *@function:使用Cuda对图像进行Sobel边缘检测 38 | *@para:*dataIn:输入图像 *dataOut:输出图像 imgHeight:图像的高 imgWidth:图像的宽 39 | *其他要注意的地方 40 | **/ 41 | //Sobel算子边缘检测核函数 42 | __global__ void sobelInCuda(unsigned char *dataIn, unsigned char *dataOut, int imgHeight, int imgWidth) 43 | { 44 | //用单thread操作 45 | int xIndex = threadIdx.x; 46 | int yIndex = xIndex/imgWidth; 47 | int index = 0; 48 | 49 | int Gx = 0; 50 | int Gy = 0; 51 | 52 | while(yIndex < imgHeight - 2) 53 | { 54 | 55 | Gx = (-1) * dataIn[(yIndex) * imgWidth + xIndex] + 0*dataIn[(yIndex +1 ) * imgWidth + xIndex] + 1*dataIn[(yIndex + 2) * imgWidth + xIndex] 56 | + (-2) * dataIn[(yIndex) * imgWidth + xIndex + 1] + 0 * dataIn[(yIndex+1) * imgWidth + xIndex + 1] + 2 * dataIn[(yIndex + 2) * imgWidth + xIndex + 1] 57 | + (-1) * dataIn[(yIndex) * imgWidth + xIndex + 2] + 0 * dataIn[(yIndex+1) * imgWidth + xIndex + 2] + 1 * dataIn[(yIndex + 2) * imgWidth + xIndex + 2]; 58 | Gy = (-1) * dataIn[(yIndex) * imgWidth + xIndex] + (-2) * dataIn[(yIndex +1 ) * imgWidth + xIndex] + (-1)*dataIn[(yIndex + 2) * imgWidth + xIndex] 59 | + (0) * dataIn[(yIndex) * imgWidth + xIndex + 1] + 0 * dataIn[(yIndex+1) * imgWidth + xIndex + 1] + 0 * dataIn[(yIndex + 2) * imgWidth + xIndex + 1] 60 | + (1) * dataIn[(yIndex) * imgWidth + xIndex + 2] + 2 * dataIn[(yIndex+1) * imgWidth + xIndex + 2] + 1 * dataIn[(yIndex + 2) * imgWidth + xIndex + 2]; 61 | int sum = abs(Gx) + abs(Gy); 62 | if (sum > 255) 63 | { 64 | sum = 255; //for best performance 65 | } 66 | dataOut[index] = sum; 67 | xIndex ++; 68 | if ( xIndex == imgWidth-2 ) 69 | { 70 | xIndex = 0; 71 | yIndex ++; 72 | } 73 | index = xIndex + yIndex * imgWidth; 74 | } 75 | } 76 | 77 | /** 78 | *@author:Seafood 79 | *@name:sobelCpuPixel() 80 | *@return:void 81 | *@function:使用CPU对图像像素进行Sobel边缘检测 82 | *@para:None 83 | *其他要注意的地方 84 | **/ 85 | //Sobel算子边缘检测CPU函数 86 | void sobelCpuPixel() 87 | { 88 | clock_t begin_time, end_clock; 89 | begin_time = clock(); 90 | 91 | int sobel_x[3][3]; 92 | int sobel_y[3][3]; 93 | 94 | // asigning values to sobel x direction 95 | sobel_x[0][0] = -1; sobel_x[0][1] = 0; sobel_x[0][2] =1; 96 | sobel_x[1][0] = -2; sobel_x[1][1] = 0; sobel_x[1][2] =2; 97 | sobel_x[2][0] = -1; sobel_x[2][1] = 0; sobel_x[2][2] =1; 98 | // asigning values to sobel y direction 99 | sobel_y[0][0] = -1; sobel_y[0][1] = -2; sobel_y[0][2] = -1; 100 | sobel_y[1][0] = 0; sobel_y[1][1] = 0; sobel_y[1][2] = 0; 101 | sobel_y[2][0] = 1; sobel_y[2][1] = 2; sobel_y[2][2] = 1; 102 | 103 | Mat img = g_gaussImage; 104 | Mat newimg = img; 105 | 106 | for (int j = 0; j(j,i)) + (sobel_x[0][1] * (int)img.at(j+1,i)) + (sobel_x[0][2] * (int)img.at(j+2,i)) + 112 | (sobel_x[1][0] * (int)img.at(j,i+1)) + (sobel_x[1][1] * (int)img.at(j+1,i+1)) + (sobel_x[1][2] * (int)img.at(j+2,i+1)) + 113 | (sobel_x[2][0] * (int)img.at(j,i+2)) + (sobel_x[2][1] * (int)img.at(j+1,i+2)) + (sobel_x[2][2] * (int)img.at(j+2,i+2)); 114 | 115 | int pixval_y = 116 | (sobel_y[0][0] * (int)img.at(j,i)) + (sobel_y[0][1] * (int)img.at(j+1,i)) + (sobel_y[0][2] * (int)img.at(j+2,i)) + 117 | (sobel_y[1][0] * (int)img.at(j,i+1)) + (sobel_y[1][1] * (int)img.at(j+1,i+1)) + (sobel_y[1][2] * (int)img.at(j+2,i+1)) + 118 | (sobel_y[2][0] * (int)img.at(j,i+2)) + (sobel_y[2][1] * (int)img.at(j+1,i+2)) + (sobel_y[2][2] * (int)img.at(j+2,i+2)); 119 | 120 | int sum = abs(pixval_x) + abs(pixval_y); 121 | if (sum > 255) 122 | { 123 | sum = 255; //for best performance 124 | } 125 | newimg.at(j,i) = sum; 126 | } 127 | } 128 | end_clock = clock(); 129 | cout << "CPU对像素操作运行时间为: " << static_cast(end_clock - begin_time) / CLOCKS_PER_SEC*1000 << "ms" << endl;//输出运行时间为毫秒 130 | cvNamedWindow("processed_by_CPUinPaxel", 0); 131 | resizeWindow("processed_by_CPUinPaxel", 800, 600); 132 | imshow("processed_by_CPUinPaxel", newimg); 133 | } 134 | 135 | /** 136 | *@author:Seafood 137 | *@name:sobelCpuPackage 138 | *@return:void 139 | *@function:使用CPU的OPENCV包对图像进行Sobel边缘检测 140 | *@para:None 141 | *其他要注意的地方 142 | **/ 143 | //Sobel算子边缘检测CPU函数 144 | 145 | void sobelCpuPackage(int, void*) 146 | { 147 | clock_t begin_time, end_clock; 148 | begin_time = clock(); 149 | //求x方向梯度 150 | Sobel(g_grayImage, g_sobelGradient_X, CV_16S, 1, 0, (2*g_sobelKernelSize + 1), 1, 1, BORDER_DEFAULT); 151 | convertScaleAbs( g_sobelGradient_X, g_sobelAbsGradient_X); 152 | 153 | //求Y方向梯度 154 | Sobel(g_grayImage, g_sobelGradient_Y, CV_16S, 1, 0, (2*g_sobelKernelSize + 1), 1, 1, BORDER_DEFAULT); 155 | convertScaleAbs( g_sobelGradient_Y, g_sobelAbsGradient_Y); 156 | 157 | //合并梯度 158 | addWeighted(g_sobelAbsGradient_X, 0.5, g_sobelAbsGradient_Y, 0.5,0,dst_Cpu ); 159 | end_clock = clock(); 160 | cout << "CPU对使用OPENCV包操作运行时间为: " << static_cast(end_clock - begin_time) / CLOCKS_PER_SEC*1000 << "ms" << endl;//输出运行时间为毫秒 161 | cvNamedWindow("CPU处理效果图(OPENCV包)", 0); 162 | resizeWindow("CPU处理效果图(OPENCV包)", 800, 600); 163 | imshow("CPU处理效果图(OPENCV包)", dst_Cpu); 164 | } 165 | 166 | /** 167 | *@author:Seafood 168 | *@name:pictureInit(void) 169 | *@return:void 170 | *@function:图像读取、高斯滤波和初始化 171 | *@para:None 172 | *其他要注意的地方 173 | **/ 174 | 175 | //图像读入 176 | void pictureInit(void) 177 | { 178 | //读入图像 179 | g_grayImage = imread("ironman.jpg", 0); 180 | 181 | //显示原图 182 | cvNamedWindow("originimage", 0); 183 | resizeWindow("originimage", 800, 600); 184 | imshow("originimage", g_grayImage); 185 | g_imgHeight = g_grayImage.rows; 186 | g_imgWidth = g_grayImage.cols; 187 | 188 | printf(" picture size is %d x %d \n", g_imgHeight, g_imgWidth); 189 | //高斯滤波 190 | GaussianBlur(g_grayImage, g_gaussImage, Size(3,3), 0, 0, BORDER_DEFAULT); 191 | g_dstImage = g_gaussImage; 192 | } 193 | /** 194 | *@author:Seafood 195 | *@name:sobelGPUPixel() 196 | *@return:void 197 | *@function:调用GPU对图像处理并计算时间 198 | *@para:None 199 | *其他要注意的地方 200 | **/ 201 | //GPU处理函数 202 | void sobelGPUPixel() 203 | { 204 | unsigned char *dev_in; 205 | unsigned char *dev_out; 206 | //创建时间用于计算 207 | cudaEvent_t start, stop; 208 | cudaEventCreate( &start ); 209 | cudaEventCreate( &stop ); 210 | //开始时间点记录 211 | cudaEventRecord( start, 0 ); 212 | 213 | //申请内存 214 | cudaMalloc((void**)&dev_in, g_imgHeight * g_imgWidth * sizeof(unsigned char)); 215 | cudaMalloc((void**)&dev_out, g_imgHeight * g_imgWidth * sizeof(unsigned char)); 216 | Mat dst_Gpu(g_imgHeight, g_imgWidth, CV_8UC1, Scalar(0)); 217 | //导入内存 218 | cudaMemcpy(dev_in, g_gaussImage.data, g_imgHeight * g_imgWidth * sizeof(unsigned char), cudaMemcpyHostToDevice); 219 | 220 | //调用核函数 221 | //单block 单thread 222 | sobelInCuda<< <1,1>> >(dev_in, dev_out, g_imgHeight, g_imgWidth); 223 | 224 | //导出处理 225 | cudaMemcpy(dst_Gpu.data, dev_out, g_imgHeight * g_imgWidth * sizeof(unsigned char), cudaMemcpyDeviceToHost); 226 | 227 | //停止时间点 228 | cudaEventRecord( stop, 0 ); 229 | cudaEventSynchronize( stop ); 230 | 231 | //释放内存 232 | cudaFree(dev_in); 233 | cudaFree(dev_out); 234 | 235 | //计算GPU所用时间 236 | float elapsedTime; 237 | cudaEventElapsedTime( &elapsedTime, start, stop ); 238 | printf( "GPU对像素操作运行时间为: %.1f ms \n", elapsedTime ); 239 | cudaEventDestroy( start ); 240 | cudaEventDestroy( stop ); 241 | 242 | //显示处理后的图像 243 | cvNamedWindow("GPU处理后的图像", 0); 244 | resizeWindow("GPU处理后的图像", 800, 600); 245 | imshow("GPU处理后的图像", dst_Gpu); 246 | } 247 | /** 248 | *@author:Seafood 249 | *@name:main(int argc, char *argv[], char **env) 250 | *@return:int 251 | *@function:程序入口,主函数 252 | *@para:None 253 | *其他要注意的地方 254 | **/ 255 | //main函数 256 | int main(int argc, char *argv[], char **env) 257 | { 258 | 259 | //图像读入和处理 260 | pictureInit(); 261 | //Sobel算子Cpu package实现 262 | 263 | sobelCpuPackage(0,0); 264 | 265 | //Sobel算子Cpu 对像素操作实现 266 | sobelCpuPixel(); 267 | 268 | //Sobel算子GPU操作实现 269 | sobelGPUPixel(); 270 | //结束展示 271 | while((char)waitKey(0) != 'q' ) 272 | { 273 | 274 | } 275 | 276 | return 0; 277 | } -------------------------------------------------------------------------------- /Sobel_4a.cu: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * 文件名:Sobel_4a.cu 3 | * 作者: 孙霖(SC19023100)(Seafood) 4 | * 说明: cudau作业之Sobel算子边缘检测第四版 5 | * 将数组存入常量内存 6 | * 7 | ****************************************************************************/ 8 | //----------------------------头文件包含和空间声明------------------------------------ 9 | #include "cuda_runtime.h" 10 | #include "cuda.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | typedef unsigned char uchar; 17 | 18 | //命名空间 19 | using namespace std; 20 | using namespace cv; 21 | 22 | //#define DIM 2048 23 | //----------------------------全局变量--------------------------------------------- 24 | Mat g_sobelGradient_X, g_sobelGradient_Y; //opencv包使用的全局变量 25 | Mat g_sobelAbsGradient_X, g_sobelAbsGradient_Y; //opencv包使用的全局变量 26 | int g_sobelKernelSize = 1; 27 | 28 | Mat dst_Cpu, g_gaussImage, g_grayImage, g_dstImage; //图像读取+高斯滤波 29 | 30 | int g_imgHeight, g_imgWidth; //图像的大小Size 31 | 32 | 33 | int sobel_x[3][3]; 34 | int sobel_y[3][3]; 35 | 36 | //cuda的常量内存 37 | __constant__ int dev_sobel_x[3][3]; 38 | __constant__ int dev_sobel_y[3][3]; 39 | /** 40 | *@author:Seafood 41 | *@name:sobelInCuda() 42 | *@return:void 43 | *@function:使用Cuda对图像进行Sobel边缘检测 44 | *@para:*dataIn:输入图像 *dataOut:输出图像 imgHeight:图像的高 imgWidth:图像的宽 45 | *其他要注意的地方 46 | **/ 47 | //Sobel算子边缘检测核函数 48 | __global__ void sobelInCuda(unsigned char *dataIn, unsigned char *dataOut, int imgHeight, int imgWidth) 49 | { 50 | //用单thread操作 51 | //int index = threadIdx.x + blockIdx.x * blockDim.x; 52 | int xIndex = threadIdx.x + blockIdx.x * blockDim.x; 53 | int yIndex = threadIdx.y + blockIdx.y * blockDim.y; 54 | int offset = xIndex + yIndex * imgWidth; 55 | //printf("blockDim: %d, gridDim: %d\n", blockDim.x, gridDim.x); 56 | //printf("xIndex : %d,yIndex : %d,Index : %d\n",xIndex, yIndex, offset); 57 | 58 | 59 | int Gx = 0; 60 | int Gy = 0; 61 | 62 | while(offset < (imgHeight - 2) * (imgWidth - 2)) 63 | { 64 | 65 | Gx = dev_sobel_x[0][0] * dataIn[(yIndex) * imgWidth + xIndex] + dev_sobel_x[0][1] * dataIn[(yIndex +1 ) * imgWidth + xIndex] + dev_sobel_x[0][2] * dataIn[(yIndex + 2) * imgWidth + xIndex] 66 | + dev_sobel_x[1][0] * dataIn[(yIndex) * imgWidth + xIndex + 1] + dev_sobel_x[1][1] * dataIn[(yIndex+1) * imgWidth + xIndex + 1] + dev_sobel_x[1][2] * dataIn[(yIndex + 2) * imgWidth + xIndex + 1] 67 | + dev_sobel_x[2][0] * dataIn[(yIndex) * imgWidth + xIndex + 2] + dev_sobel_x[2][1] * dataIn[(yIndex+1) * imgWidth + xIndex + 2] + dev_sobel_x[2][2] * dataIn[(yIndex + 2) * imgWidth + xIndex + 2]; 68 | Gy = dev_sobel_y[0][0] * dataIn[(yIndex) * imgWidth + xIndex] + dev_sobel_y[0][1] * dataIn[(yIndex +1 ) * imgWidth + xIndex] + dev_sobel_y[0][2] * dataIn[(yIndex + 2) * imgWidth + xIndex] 69 | + dev_sobel_y[1][0] * dataIn[(yIndex) * imgWidth + xIndex + 1] + dev_sobel_y[1][1] * dataIn[(yIndex+1) * imgWidth + xIndex + 1] + dev_sobel_y[1][2] * dataIn[(yIndex + 2) * imgWidth + xIndex + 1] 70 | + dev_sobel_y[2][0] * dataIn[(yIndex) * imgWidth + xIndex + 2] + dev_sobel_y[2][1] * dataIn[(yIndex+1) * imgWidth + xIndex + 2] + dev_sobel_y[2][2] * dataIn[(yIndex + 2) * imgWidth + xIndex + 2]; 71 | int sum = abs(Gx) + abs(Gy); 72 | if (sum > 255) 73 | { 74 | sum = 255; //for best performance 75 | } 76 | dataOut[offset] = sum; 77 | xIndex += blockDim.x * gridDim.x; 78 | if( xIndex > imgWidth - 2) 79 | { 80 | yIndex += blockDim.y * gridDim.y; 81 | xIndex = threadIdx.x + blockIdx.x * blockDim.x; 82 | } 83 | 84 | //offset = xIndex + yIndex * blockDim.x * gridDim.x; 85 | offset = xIndex + yIndex * imgWidth; 86 | //index = xIndex + yIndex * imgWidth; 87 | } 88 | } 89 | 90 | /** 91 | *@author:Seafood 92 | *@name:sobelCpuPixel() 93 | *@return:void016 x 401 94 | *@function:使用CPU对图像像素进行Sobel边缘检测 95 | *@para:None 96 | *其他要注意的地方 97 | **/ 98 | //Sobel算子边缘检测CPU函数 99 | void sobelCpuPixel() 100 | { 101 | clock_t begin_time, end_clock; 102 | begin_time = clock(); 103 | 104 | Mat img = g_gaussImage; 105 | Mat newimg = img; 106 | 107 | for (int j = 0; j(j,i)) + (sobel_x[0][1] * (int)img.at(j+1,i)) + (sobel_x[0][2] * (int)img.at(j+2,i)) + 113 | (sobel_x[1][0] * (int)img.at(j,i+1)) + (sobel_x[1][1] * (int)img.at(j+1,i+1)) + (sobel_x[1][2] * (int)img.at(j+2,i+1)) + 114 | (sobel_x[2][0] * (int)img.at(j,i+2)) + (sobel_x[2][1] * (int)img.at(j+1,i+2)) + (sobel_x[2][2] * (int)img.at(j+2,i+2)); 115 | 116 | int pixval_y = 117 | (sobel_y[0][0] * (int)img.at(j,i)) + (sobel_y[0][1] * (int)img.at(j+1,i)) + (sobel_y[0][2] * (int)img.at(j+2,i)) + 118 | (sobel_y[1][0] * (int)img.at(j,i+1)) + (sobel_y[1][1] * (int)img.at(j+1,i+1)) + (sobel_y[1][2] * (int)img.at(j+2,i+1)) + 119 | (sobel_y[2][0] * (int)img.at(j,i+2)) + (sobel_y[2][1] * (int)img.at(j+1,i+2)) + (sobel_y[2][2] * (int)img.at(j+2,i+2)); 120 | 121 | int sum = abs(pixval_x) + abs(pixval_y); 122 | if (sum > 255) 123 | { 124 | sum = 255; //for best performance 125 | } 126 | newimg.at(j,i) = sum; 127 | } 128 | } 129 | end_clock = clock(); 130 | cout << "CPU对像素操作运行时间为: " << static_cast(end_clock - begin_time) / CLOCKS_PER_SEC*1000 << "ms" << endl;//输出运行时间为毫秒 131 | cvNamedWindow("processed by CPU in Paxel", 0); 132 | resizeWindow("processed by CPU in Paxel", 800, 600); 133 | imshow("processed by CPU in Paxel", newimg); 134 | } 135 | 136 | /** 137 | *@author:Seafood 138 | *@name:sobelCpuPackage 139 | *@return:void 140 | *@function:使用CPU的OPENCV包对图像进行Sobel边缘检测 141 | *@para:None 142 | *其他要注意的地方 143 | **/ 144 | //Sobel算子边缘检测CPU函数 145 | 146 | void sobelCpuPackage(int, void*) 147 | { 148 | clock_t begin_time, end_clock; 149 | begin_time = clock(); 150 | //求x方向梯度 151 | Sobel(g_grayImage, g_sobelGradient_X, CV_16S, 1, 0, (2*g_sobelKernelSize + 1), 1, 1, BORDER_DEFAULT); 152 | convertScaleAbs( g_sobelGradient_X, g_sobelAbsGradient_X); 153 | 154 | //求Y方向梯度 155 | Sobel(g_grayImage, g_sobelGradient_Y, CV_16S, 1, 0, (2*g_sobelKernelSize + 1), 1, 1, BORDER_DEFAULT); 156 | convertScaleAbs( g_sobelGradient_Y, g_sobelAbsGradient_Y); 157 | 158 | //合并梯度 159 | addWeighted(g_sobelAbsGradient_X, 0.5, g_sobelAbsGradient_Y, 0.5,0,dst_Cpu ); 160 | end_clock = clock(); 161 | cout << "CPU对使用OPENCV包操作运行时间为: " << static_cast(end_clock - begin_time) / CLOCKS_PER_SEC*1000 << "ms" << endl;//输出运行时间为毫秒 162 | cvNamedWindow("CPU处理效果图(OPENCV包)", 0); 163 | resizeWindow("CPU处理效果图(OPENCV包)", 800, 600); 164 | imshow("CPU处理效果图(OPENCV包)", dst_Cpu); 165 | } 166 | 167 | /** 168 | *@author:Seafood 169 | *@name:pictureInit(void) 170 | *@return:void 171 | *@function:图像读取、高斯滤波和初始化 172 | *@para:None 173 | *其他要注意的地方 174 | **/ 175 | 176 | //图像读入 177 | void pictureInit(void) 178 | { 179 | //读入图像 180 | g_grayImage = imread("rmpicture.png", 0); 181 | 182 | //显示原图 183 | cvNamedWindow("originimage", 0); 184 | resizeWindow("originimage", 800, 600); 185 | imshow("originimage", g_grayImage); 186 | g_imgHeight = g_grayImage.rows; 187 | g_imgWidth = g_grayImage.cols; 188 | 189 | // asigning values to sobel x direction 190 | sobel_x[0][0] = -1; sobel_x[0][1] = 0; sobel_x[0][2] =1; 191 | sobel_x[1][0] = -2; sobel_x[1][1] = 0; sobel_x[1][2] =2; 192 | sobel_x[2][0] = -1; sobel_x[2][1] = 0; sobel_x[2][2] =1; 193 | // asigning values to sobel y direction 194 | sobel_y[0][0] = -1; sobel_y[0][1] = -2; sobel_y[0][2] = -1; 195 | sobel_y[1][0] = 0; sobel_y[1][1] = 0; sobel_y[1][2] = 0; 196 | sobel_y[2][0] = 1; sobel_y[2][1] = 2; sobel_y[2][2] = 1; 197 | printf(" picture size is %d x %d \n", g_imgHeight, g_imgWidth); 198 | //高斯滤波 199 | GaussianBlur(g_grayImage, g_gaussImage, Size(3,3), 0, 0, BORDER_DEFAULT); 200 | g_dstImage = g_gaussImage; 201 | } 202 | /** 203 | *@author:Seafood 204 | *@name:sobelGPUPixel() 205 | *@return:void 206 | *@function:调用GPU对图像处理并计算时间 207 | *@para:None 208 | *其他要注意的地方 209 | **/ 210 | //GPU处理函数 211 | void sobelGPUPixel() 212 | { 213 | //创建时间用于计算 214 | cudaEvent_t start, stop; 215 | cudaEventCreate( &start ); 216 | cudaEventCreate( &stop ); 217 | //开始时间点记录 218 | cudaEventRecord( start, 0 ); 219 | //定义变量 220 | unsigned char *dev_in; 221 | unsigned char *dev_out; 222 | 223 | Mat dst_Gpu(g_imgHeight, g_imgWidth, CV_8UC1, Scalar(0)); 224 | 225 | 226 | //定义数组 227 | 228 | //申请内存 229 | cudaMalloc((void**)&dev_in, g_imgHeight * g_imgWidth * sizeof(unsigned char)); 230 | cudaMalloc((void**)&dev_out, g_imgHeight * g_imgWidth * sizeof(unsigned char)); 231 | //导入内存 232 | cudaMemcpy(dev_in, g_gaussImage.data, g_imgHeight * g_imgWidth * sizeof(unsigned char), cudaMemcpyHostToDevice); 233 | 234 | //数组导入 235 | cudaMemcpyToSymbol(dev_sobel_x, sobel_x, sizeof(int) * 3 * 3 ); 236 | cudaMemcpyToSymbol(dev_sobel_y, sobel_y, sizeof(int) * 3 * 3 ); 237 | //调用核函数 238 | //定义block thread范围 239 | dim3 blocks((int)((g_imgWidth+31)/32), (int)(g_imgHeight+31)/32); 240 | //dim3 blocks(1, 1); 241 | dim3 threads(16, 16); 242 | //单block 单thread 243 | sobelInCuda<< <4,4>> >(dev_in, dev_out, g_imgHeight, g_imgWidth); 244 | 245 | //导出处理 246 | cudaMemcpy(dst_Gpu.data, dev_out, g_imgHeight * g_imgWidth * sizeof(unsigned char), cudaMemcpyDeviceToHost); 247 | 248 | //停止时间点 249 | cudaEventRecord( stop, 0 ); 250 | cudaEventSynchronize( stop ); 251 | //释放内存 252 | cudaFree(dev_in); 253 | cudaFree(dev_out); 254 | cudaFree(dev_sobel_x); 255 | cudaFree(dev_sobel_y); 256 | 257 | 258 | 259 | //计算GPU所用时间 260 | float elapsedTime; 261 | cudaEventElapsedTime( &elapsedTime, start, stop ); 262 | printf( "GPU对像素操作运行时间为: %.1f ms \n", elapsedTime ); 263 | cudaEventDestroy( start ); 264 | cudaEventDestroy( stop ); 265 | 266 | //显示处理后的图像 267 | cvNamedWindow("GPU处理后的图像", 0); 268 | resizeWindow("GPU处理后的图像", 800, 600); 269 | imshow("GPU处理后的图像", dst_Gpu); 270 | } 271 | /** 272 | *@author:Seafood 273 | *@name:main(int argc, char *argv[], char **env) 274 | *@return:int 275 | *@function:程序入口,主函数 276 | *@para:None 277 | *其他要注意的地方 278 | **/ 279 | //main函数 280 | int main(int argc, char *argv[], char **env) 281 | { 282 | 283 | //图像读入和处理 284 | pictureInit(); 285 | //Sobel算子Cpu package实现 286 | 287 | sobelCpuPackage(0,0); 288 | 289 | //Sobel算子Cpu 对像素操作实现 290 | sobelCpuPixel(); 291 | 292 | //Sobel算子GPU操作实现 293 | sobelGPUPixel(); 294 | //结束展示 295 | while((char)waitKey(0) != 'q' ) 296 | { 297 | 298 | } 299 | 300 | return 0; 301 | } -------------------------------------------------------------------------------- /Sobel_3.cu: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * 文件名:Sobel_3.cu 3 | * 作者: 孙霖(SC19023100)(Seafood) 4 | * 说明: cudau作业之Sobel算子边缘检测第三版 5 | * 使用多block多thread对GPU程序进行优化二维 6 | ****************************************************************************/ 7 | //----------------------------头文件包含和空间声明------------------------------------ 8 | #include "cuda_runtime.h" 9 | #include "cuda.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | typedef unsigned char uchar; 17 | 18 | //命名空间 19 | using namespace std; 20 | using namespace cv; 21 | 22 | //#define DIM 2048 23 | //----------------------------全局变量--------------------------------------------- 24 | Mat g_sobelGradient_X, g_sobelGradient_Y; //opencv包使用的全局变量 25 | Mat g_sobelAbsGradient_X, g_sobelAbsGradient_Y; //opencv包使用的全局变量 26 | int g_sobelKernelSize = 1; 27 | 28 | Mat dst_Cpu, g_gaussImage, g_grayImage, g_dstImage; //图像读取+高斯滤波 29 | 30 | int g_imgHeight, g_imgWidth; //图像的大小Size 31 | 32 | //变换矩阵 33 | int sobel_x[3][3]; 34 | 35 | int sobel_y[3][3]; 36 | /** 37 | *@author:Seafood 38 | *@name:sobelInCuda() 39 | *@return:void 40 | *@function:使用Cuda对图像进行Sobel边缘检测 41 | *@para:*dataIn:输入图像 *dataOut:输出图像 imgHeight:图像的高 imgWidth:图像的宽 42 | *其他要注意的地方 43 | **/ 44 | //Sobel算子边缘检测核函数 45 | __global__ void sobelInCuda(unsigned char *dataIn, unsigned char *dataOut, int imgHeight, int imgWidth, int *dev_sobel_x, int *dev_sobel_y) 46 | { 47 | //用单thread操作 48 | //int index = threadIdx.x + blockIdx.x * blockDim.x; 49 | int xIndex = threadIdx.x + blockIdx.x * blockDim.x; 50 | int yIndex = threadIdx.y + blockIdx.y * blockDim.y; 51 | int offset = xIndex + yIndex * imgWidth; 52 | //printf("blockDim: %d, gridDim: %d\n", blockDim.x, gridDim.x); 53 | //printf("xIndex : %d,yIndex : %d,Index : %d\n",xIndex, yIndex, offset); 54 | 55 | int Gx = 0; 56 | int Gy = 0; 57 | 58 | while(offset < (imgHeight - 2) * (imgWidth - 2)) 59 | { 60 | 61 | Gx = dev_sobel_x[0] * dataIn[(yIndex) * imgWidth + xIndex] + dev_sobel_x[1] * dataIn[(yIndex +1 ) * imgWidth + xIndex] + dev_sobel_x[2] * dataIn[(yIndex + 2) * imgWidth + xIndex] 62 | + dev_sobel_x[3] * dataIn[(yIndex) * imgWidth + xIndex + 1] + dev_sobel_x[4] * dataIn[(yIndex+1) * imgWidth + xIndex + 1] + dev_sobel_x[5] * dataIn[(yIndex + 2) * imgWidth + xIndex + 1] 63 | + dev_sobel_x[6] * dataIn[(yIndex) * imgWidth + xIndex + 2] + dev_sobel_x[7] * dataIn[(yIndex+1) * imgWidth + xIndex + 2] + dev_sobel_x[8] * dataIn[(yIndex + 2) * imgWidth + xIndex + 2]; 64 | Gy = dev_sobel_y[0] * dataIn[(yIndex) * imgWidth + xIndex] + dev_sobel_y[1] * dataIn[(yIndex +1 ) * imgWidth + xIndex] + dev_sobel_y[2] * dataIn[(yIndex + 2) * imgWidth + xIndex] 65 | + dev_sobel_y[3] * dataIn[(yIndex) * imgWidth + xIndex + 1] + dev_sobel_y[4] * dataIn[(yIndex+1) * imgWidth + xIndex + 1] + dev_sobel_y[5] * dataIn[(yIndex + 2) * imgWidth + xIndex + 1] 66 | + dev_sobel_y[6] * dataIn[(yIndex) * imgWidth + xIndex + 2] + dev_sobel_y[7] * dataIn[(yIndex+1) * imgWidth + xIndex + 2] + dev_sobel_y[8] * dataIn[(yIndex + 2) * imgWidth + xIndex + 2]; 67 | int sum = abs(Gx) + abs(Gy); 68 | if (sum > 255) 69 | { 70 | sum = 255; //for best performance 71 | } 72 | dataOut[offset] = sum; 73 | xIndex += blockDim.x * gridDim.x; 74 | if( xIndex > imgWidth - 2) 75 | { 76 | yIndex += blockDim.y * gridDim.y; 77 | xIndex = threadIdx.x + blockIdx.x * blockDim.x; 78 | } 79 | 80 | //offset = xIndex + yIndex * blockDim.x * gridDim.x; 81 | offset = xIndex + yIndex * imgWidth; 82 | //index = xIndex + yIndex * imgWidth; 83 | } 84 | } 85 | 86 | /** 87 | *@author:Seafood 88 | *@name:sobelCpuPixel() 89 | *@return:void016 x 401 90 | *@function:使用CPU对图像像素进行Sobel边缘检测 91 | *@para:None 92 | *其他要注意的地方 93 | **/ 94 | //Sobel算子边缘检测CPU函数 95 | void sobelCpuPixel() 96 | { 97 | clock_t begin_time, end_clock; 98 | begin_time = clock(); 99 | 100 | 101 | Mat img = g_gaussImage; 102 | Mat newimg = img; 103 | 104 | for (int j = 0; j(j,i)) + (sobel_x[0][1] * (int)img.at(j+1,i)) + (sobel_x[0][2] * (int)img.at(j+2,i)) + 110 | (sobel_x[1][0] * (int)img.at(j,i+1)) + (sobel_x[1][1] * (int)img.at(j+1,i+1)) + (sobel_x[1][2] * (int)img.at(j+2,i+1)) + 111 | (sobel_x[2][0] * (int)img.at(j,i+2)) + (sobel_x[2][1] * (int)img.at(j+1,i+2)) + (sobel_x[2][2] * (int)img.at(j+2,i+2)); 112 | 113 | int pixval_y = 114 | (sobel_y[0][0] * (int)img.at(j,i)) + (sobel_y[0][1] * (int)img.at(j+1,i)) + (sobel_y[0][2] * (int)img.at(j+2,i)) + 115 | (sobel_y[1][0] * (int)img.at(j,i+1)) + (sobel_y[1][1] * (int)img.at(j+1,i+1)) + (sobel_y[1][2] * (int)img.at(j+2,i+1)) + 116 | (sobel_y[2][0] * (int)img.at(j,i+2)) + (sobel_y[2][1] * (int)img.at(j+1,i+2)) + (sobel_y[2][2] * (int)img.at(j+2,i+2)); 117 | 118 | int sum = abs(pixval_x) + abs(pixval_y); 119 | if (sum > 255) 120 | { 121 | sum = 255; //for best performance 122 | } 123 | newimg.at(j,i) = sum; 124 | } 125 | } 126 | end_clock = clock(); 127 | cout << "CPU对像素操作运行时间为: " << static_cast(end_clock - begin_time) / CLOCKS_PER_SEC*1000 << "ms" << endl;//输出运行时间为毫秒 128 | cvNamedWindow("processed by CPU in Paxel", 0); 129 | resizeWindow("processed by CPU in Paxel", 800, 600); 130 | imshow("processed by CPU in Paxel", newimg); 131 | } 132 | 133 | /** 134 | *@author:Seafood 135 | *@name:sobelCpuPackage 136 | *@return:void 137 | *@function:使用CPU的OPENCV包对图像进行Sobel边缘检测 138 | *@para:None 139 | *其他要注意的地方 140 | **/ 141 | //Sobel算子边缘检测CPU函数 142 | 143 | void sobelCpuPackage(int, void*) 144 | { 145 | clock_t begin_time, end_clock; 146 | begin_time = clock(); 147 | //求x方向梯度 148 | Sobel(g_grayImage, g_sobelGradient_X, CV_16S, 1, 0, (2*g_sobelKernelSize + 1), 1, 1, BORDER_DEFAULT); 149 | convertScaleAbs( g_sobelGradient_X, g_sobelAbsGradient_X); 150 | 151 | //求Y方向梯度 152 | Sobel(g_grayImage, g_sobelGradient_Y, CV_16S, 1, 0, (2*g_sobelKernelSize + 1), 1, 1, BORDER_DEFAULT); 153 | convertScaleAbs( g_sobelGradient_Y, g_sobelAbsGradient_Y); 154 | 155 | //合并梯度 156 | addWeighted(g_sobelAbsGradient_X, 0.5, g_sobelAbsGradient_Y, 0.5,0,dst_Cpu ); 157 | end_clock = clock(); 158 | cout << "CPU对使用OPENCV包操作运行时间为: " << static_cast(end_clock - begin_time) / CLOCKS_PER_SEC*1000 << "ms" << endl;//输出运行时间为毫秒 159 | cvNamedWindow("CPU处理效果图(OPENCV包)", 0); 160 | resizeWindow("CPU处理效果图(OPENCV包)", 800, 600); 161 | imshow("CPU处理效果图(OPENCV包)", dst_Cpu); 162 | } 163 | 164 | /** 165 | *@author:Seafood 166 | *@name:pictureInit(void) 167 | *@return:void 168 | *@function:图像读取、高斯滤波sobel_y[8]和初始化 169 | *@para:None 170 | *其他要注意的地方 171 | **/ 172 | 173 | //图像读入 174 | void pictureInit(void) 175 | { 176 | //读入图像 177 | g_grayImage = imread("rmpicture.png", 0); 178 | 179 | //显示原图 180 | cvNamedWindow("originimage", 0); 181 | resizeWindow("originimage", 800, 600); 182 | imshow("originimage", g_grayImage); 183 | g_imgHeight = g_grayImage.rows; 184 | g_imgWidth = g_grayImage.cols; 185 | 186 | // asigning values to sobel x direction 187 | sobel_x[0][0] = -1; sobel_x[0][1] = 0; sobel_x[0][2] =1; 188 | sobel_x[1][0] = -2; sobel_x[1][1] = 0; sobel_x[1][2] =2; 189 | sobel_x[2][0] = -1; sobel_x[2][1] = 0; sobel_x[2][2] =1; 190 | // asigning values to sobel y direction 191 | sobel_y[0][0] = -1; sobel_y[0][1] = -2; sobel_y[0][2] = -1; 192 | sobel_y[1][0] = 0; sobel_y[1][1] = 0; sobel_y[1][2] = 0; 193 | sobel_y[2][0] = 1; sobel_y[2][1] = 2; sobel_y[2][2] = 1; 194 | 195 | printf(" picture size is %d x %d \n", g_imgHeight, g_imgWidth); 196 | //高斯滤波 197 | GaussianBlur(g_grayImage, g_gaussImage, Size(3,3), 0, 0, BORDER_DEFAULT); 198 | g_dstImage = g_gaussImage; 199 | } 200 | /** 201 | *@author:Seafood 202 | *@name:sobelGPUPixel() 203 | *@return:void 204 | *@function:调用GPU对图像处理并计算时间 205 | *@para:None 206 | *其他要注意的地方 207 | **/ 208 | //GPU处理函数sobel_y[8] 209 | void sobelGPUPixel() 210 | { 211 | //创建时间用于计算 212 | cudaEvent_t start, stop; 213 | cudaEventCreate( &start ); 214 | cudaEventCreate( &stop ); 215 | //开始时间点记录 216 | cudaEventRecord( start, 0 ); 217 | unsigned char *dev_in; 218 | unsigned char *dev_out; 219 | //数组 220 | int *dev_sobel_x; 221 | int *dev_sobel_y; 222 | Mat dst_Gpu(g_imgHeight, g_imgWidth, CV_8UC1, Scalar(0)); 223 | 224 | //申请内存 225 | cudaMalloc((void**)&dev_in, g_imgHeight * g_imgWidth * sizeof(unsigned char)); 226 | cudaMalloc((void**)&dev_out, g_imgHeight * g_imgWidth * sizeof(unsigned char)); 227 | cudaMalloc((void**)&dev_sobel_x, 9 * sizeof(int)); 228 | cudaMalloc((void**)&dev_sobel_y, 9 * sizeof(int)); 229 | //导入内存 230 | cudaMemcpy(dev_in, g_gaussImage.data, g_imgHeight * g_imgWidth * sizeof(unsigned char), cudaMemcpyHostToDevice); 231 | cudaMemcpy((void*)dev_sobel_x, (void*)sobel_x, 3 *3* sizeof(int), cudaMemcpyHostToDevice); 232 | cudaMemcpy((void*)dev_sobel_y, (void*)sobel_y, 3 *3* sizeof(int), cudaMemcpyHostToDevice); 233 | //调用核函数 234 | 235 | //定义block thread范围 236 | dim3 blocks((int)((g_imgWidth+31)/32), (int)(g_imgHeight+31)/32); 237 | dim3 threads(16, 16); 238 | sobelInCuda<< > >(dev_in, dev_out, g_imgHeight, g_imgWidth, dev_sobel_x, dev_sobel_y); 239 | 240 | //导出处理 241 | cudaMemcpy(dst_Gpu.data, dev_out, g_imgHeight * g_imgWidth * sizeof(unsigned char), cudaMemcpyDeviceToHost); 242 | 243 | //停止时间点 244 | cudaEventRecord( stop, 0 ); 245 | cudaEventSynchronize( stop ); 246 | //释放内存 247 | cudaFree(dev_in); 248 | cudaFree(dev_out); 249 | 250 | 251 | //计算GPU所用时间 252 | float elapsedTime; 253 | cudaEventElapsedTime( &elapsedTime, start, stop ); 254 | printf( "GPU对像素操作运行时间为 : %.1f ms \n", elapsedTime ); 255 | cudaEventDestroy( start ); 256 | cudaEventDestroy( stop ); 257 | 258 | //显示处理后的图像 259 | cvNamedWindow("GPU处理后的图像", 0); 260 | resizeWindow("GPU处理后的图像", 800, 600); 261 | imshow("GPU处理后的图像", dst_Gpu); 262 | } 263 | /** 264 | *@author:Seafood 265 | *@name:main(int argc, char *argv[], char **env) 266 | *@return:int 267 | *@function:程序入口,主函数 268 | *@para:None 269 | *其他要注意的地方 270 | **/ 271 | //main函数 272 | int main(int argc, char *argv[], char **env) 273 | { 274 | 275 | //图像读入和处理 276 | pictureInit(); 277 | //Sobel算子Cpu package实现 278 | 279 | sobelCpuPackage(0,0); 280 | 281 | //Sobel算子Cpu 对像素操作实现 282 | sobelCpuPixel(); 283 | 284 | //Sobel算子GPU操作实现 285 | sobelGPUPixel(); 286 | //结束展示 287 | while((char)waitKey(0) != 'q' ) 288 | { 289 | 290 | } 291 | 292 | return 0; 293 | } -------------------------------------------------------------------------------- /Sobel_4b.cu: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * 文件名:Sobel_4b.cu 3 | * 作者: 孙霖(SC19023100)(Seafood) 4 | * 说明: cudau作业之Sobel算子边缘检测第四版 5 | * 将数组存入纹理内存 6 | * 7 | ****************************************************************************/ 8 | //----------------------------头文件包含和空间声明------------------------------------ 9 | #include "cuda_runtime.h" 10 | #include "cuda.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | typedef unsigned char uchar; 17 | 18 | //命名空间 19 | using namespace std; 20 | using namespace cv; 21 | 22 | //#define DIM 2048 23 | //----------------------------全局变量--------------------------------------------- 24 | Mat g_sobelGradient_X, g_sobelGradient_Y; //opencv包使用的全局变量 25 | Mat g_sobelAbsGradient_X, g_sobelAbsGradient_Y; //opencv包使用的全局变量 26 | int g_sobelKernelSize = 1; 27 | 28 | 29 | Mat dst_Cpu, g_gaussImage, g_grayImage, g_dstImage; //图像读取+高斯滤波 30 | 31 | int g_imgHeight, g_imgWidth; //图像的大小Size 32 | 33 | 34 | int sobel_x[3][3]; 35 | int sobel_y[3][3]; 36 | int number = 1025; 37 | //cuda的常量内存 38 | __constant__ int dev_sobel_x[3][3]; 39 | __constant__ int dev_sobel_y[3][3]; 40 | 41 | //纹理内存 42 | texture texIn; 43 | /** 44 | *@author:Seafood 45 | *@name:sobelInCuda() 46 | *@return:void 47 | *@function:使用Cuda对图像进行Sobel边缘检测 48 | *@para:*dataIn:输入图像 *dataOut:输出图像 imgHeight:图像的高 imgWidth:图像的宽 49 | *其他要注意的地方 50 | **/ 51 | //Sobel算子边缘检测核函数 52 | __global__ void sobelInCuda(unsigned char *dataOut, int imgHeight, int imgWidth) 53 | { 54 | //用单thread操作 55 | //int index = threadIdx.x + blockIdx.x * blockDim.x; 56 | int xIndex = threadIdx.x + blockIdx.x * blockDim.x; 57 | int yIndex = threadIdx.y + blockIdx.y * blockDim.y; 58 | int offset = xIndex + yIndex * imgWidth; 59 | //printf("blockDim: %d, gridDim: %d\n", blockDim.x, gridDim.x); 60 | //printf("xIndex : %d,yIndex : %d,Index : %d\n",xIndex, yIndex, offset); 61 | /* 62 | if(threadIdx.x == 1 && blockIdx.x == 1) 63 | { 64 | for(int i = 0;i < 3; i++) 65 | { 66 | printf("%d %d %d\n", dev_sobel_y[i][0],dev_sobel_y[i][1],dev_sobel_y[i][2]); 67 | } 68 | printf("gpu用的高斯图像%s\n", tex1Dfetch(texIn, 1025*imgWidth + 1025)); 69 | }*/ 70 | 71 | int tex_00,tex_01,tex_02,tex_10,tex_11,tex_12,tex_20,tex_21,tex_22; 72 | int Gx = 0; 73 | int Gy = 0; 74 | 75 | //printf("NonTex: %d \nTex: %d \n", dataIn[offset+ imgWidth* 2], tex1D(texIn, offset+ imgWidth* 2)); 76 | 77 | while(offset < (imgHeight - 2) * (imgWidth - 2)) 78 | { 79 | //纹理内存上下左右 80 | int down_00 = offset; int down_01 = down_00 + 1; int down_02 = down_00 + 2; 81 | int down_10 = offset + imgWidth; int down_11 = down_10 + 1; int down_12 = down_10 + 2; 82 | int down_20 = offset + imgWidth * 2; int down_21 = down_20 + 1; int down_22 = down_20 + 2; 83 | 84 | tex_00 = tex1Dfetch(texIn, down_00); tex_01 = tex1Dfetch(texIn, down_01); tex_02 = tex1Dfetch(texIn, down_02); 85 | tex_10 = tex1Dfetch(texIn, down_10); tex_11 = tex1Dfetch(texIn, down_11); tex_12 = tex1Dfetch(texIn, down_12); 86 | tex_20 = tex1Dfetch(texIn, down_20); tex_21 = tex1Dfetch(texIn, down_21); tex_22 = tex1Dfetch(texIn, down_22); 87 | 88 | Gx = dev_sobel_x[0][0] * tex_00 + dev_sobel_x[0][1] * tex_01 + dev_sobel_x[0][2] * tex_02 89 | + dev_sobel_x[1][0] * tex_10 + dev_sobel_x[1][1] * tex_11 + dev_sobel_x[1][2] * tex_12 90 | + dev_sobel_x[2][0] * tex_20 + dev_sobel_x[2][1] * tex_21 + dev_sobel_x[2][2] * tex_22; 91 | Gy = dev_sobel_y[0][0] * tex_00 + dev_sobel_y[0][1] * tex_01 + dev_sobel_y[0][2] * tex_02 92 | + dev_sobel_y[1][0] * tex_10 + dev_sobel_y[1][1] * tex_11 + dev_sobel_y[1][2] * tex_12 93 | + dev_sobel_y[2][0] * tex_20 + dev_sobel_y[2][1] * tex_21 + dev_sobel_y[2][2] * tex_22; 94 | 95 | int sum = abs(Gx) + abs(Gy); 96 | //int sum = Gx; 97 | if (sum > 255) 98 | { 99 | sum = 255; //for best performance 100 | } 101 | if (sum < 0) sum = 0; 102 | dataOut[offset] = (int)sum; 103 | xIndex += blockDim.x * gridDim.x; 104 | if( xIndex > imgWidth) 105 | { 106 | yIndex += blockDim.y * gridDim.y; 107 | xIndex = threadIdx.x + blockIdx.x * blockDim.x; 108 | } 109 | 110 | //offset = xIndex + yIndex * blockDim.x * gridDim.x; 111 | offset = xIndex + yIndex * imgWidth; 112 | //index = xIndex + yIndex * imgWidth; 113 | } 114 | } 115 | 116 | /** 117 | *@author:Seafood 118 | *@name:sobelCpuPixel() 119 | *@return:void016 x 401 120 | *@function:使用CPU对图像像素进行Sobel边缘检测 121 | *@para:None 122 | *其他要注意的地方 123 | **/ 124 | //Sobel算子边缘检测CPU函数 125 | void sobelCpuPixel() 126 | { 127 | clock_t begin_time, end_clock; 128 | begin_time = clock(); 129 | 130 | //CPU用 131 | Mat img = g_gaussImage; 132 | Mat newimg = img; 133 | for (int j = 0; j(j,i)) + (sobel_x[0][1] * (int)img.at(j+1,i)) + (sobel_x[0][2] * (int)img.at(j+2,i)) + 139 | (sobel_x[1][0] * (int)img.at(j,i+1)) + (sobel_x[1][1] * (int)img.at(j+1,i+1)) + (sobel_x[1][2] * (int)img.at(j+2,i+1)) + 140 | (sobel_x[2][0] * (int)img.at(j,i+2)) + (sobel_x[2][1] * (int)img.at(j+1,i+2)) + (sobel_x[2][2] * (int)img.at(j+2,i+2)); 141 | 142 | int pixval_y = 143 | (sobel_y[0][0] * (int)img.at(j,i)) + (sobel_y[0][1] * (int)img.at(j+1,i)) + (sobel_y[0][2] * (int)img.at(j+2,i)) + 144 | (sobel_y[1][0] * (int)img.at(j,i+1)) + (sobel_y[1][1] * (int)img.at(j+1,i+1)) + (sobel_y[1][2] * (int)img.at(j+2,i+1)) + 145 | (sobel_y[2][0] * (int)img.at(j,i+2)) + (sobel_y[2][1] * (int)img.at(j+1,i+2)) + (sobel_y[2][2] * (int)img.at(j+2,i+2)); 146 | 147 | int sum = abs(pixval_x) + abs(pixval_y); 148 | //int sum = pixval_x; 149 | if (sum > 255) 150 | { 151 | sum = 255; //for best performance 152 | } 153 | if (sum < 0) sum = 0; 154 | newimg.at(j,i) = sum; 155 | } 156 | } 157 | end_clock = clock(); 158 | cout << "CPU对像素操作运行时间为: " << static_cast(end_clock - begin_time) / CLOCKS_PER_SEC*1000 << "ms" << endl;//输出运行时间为毫秒 159 | cvNamedWindow("processed by CPU in Paxel", 0); 160 | resizeWindow("processed by CPU in Paxel", 800, 600); 161 | imshow("processed by CPU in Paxel", newimg); 162 | } 163 | 164 | /** 165 | *@author:Seafood 166 | *@name:sobelCpuPackage 167 | *@return:void 168 | *@function:使用CPU的OPENCV包对图像进行Sobel边缘检测 169 | *@para:None 170 | *其他要注意的地方 171 | **/ 172 | //Sobel算子边缘检测CPU函数 173 | 174 | void sobelCpuPackage(int, void*) 175 | { 176 | clock_t begin_time, end_clock; 177 | begin_time = clock(); 178 | //求x方向梯度 179 | Sobel(g_grayImage, g_sobelGradient_X, CV_16S, 1, 0, (2*g_sobelKernelSize + 1), 1, 1, BORDER_DEFAULT); 180 | convertScaleAbs( g_sobelGradient_X, g_sobelAbsGradient_X); 181 | 182 | //求Y方向梯度 183 | Sobel(g_grayImage, g_sobelGradient_Y, CV_16S, 1, 0, (2*g_sobelKernelSize + 1), 1, 1, BORDER_DEFAULT); 184 | convertScaleAbs( g_sobelGradient_Y, g_sobelAbsGradient_Y); 185 | 186 | //合并梯度 187 | addWeighted(g_sobelAbsGradient_X, 0.5, g_sobelAbsGradient_Y, 0.5,0,dst_Cpu ); 188 | end_clock = clock(); 189 | cout << "CPU对使用OPENCV包操作运行时间为: " << static_cast(end_clock - begin_time) / CLOCKS_PER_SEC*1000 << "ms" << endl;//输出运行时间为毫秒 190 | cvNamedWindow("CPU处理效果图(OPENCV包)", 0); 191 | resizeWindow("CPU处理效果图(OPENCV包)", 800, 600); 192 | imshow("CPU处理效果图(OPENCV包)", dst_Cpu); 193 | } 194 | 195 | /** 196 | *@author:Seafood 197 | *@name:pictureInit(void) 198 | *@return:void 199 | *@function:图像读取、高斯滤波和初始化 200 | *@para:None 201 | *其他要注意的地方 202 | **/ 203 | 204 | //图像读入 205 | void pictureInit(void) 206 | { 207 | //读入图像 208 | g_grayImage = imread("rmpicture.png", 0); 209 | 210 | //显示原图 211 | cvNamedWindow("originimage", 0); 212 | resizeWindow("originimage", 800, 600); 213 | imshow("originimage", g_grayImage); 214 | g_imgHeight = g_grayImage.rows; 215 | g_imgWidth = g_grayImage.cols; 216 | 217 | // asigning values to sobel x direction 218 | sobel_x[0][0] = -1; sobel_x[0][1] = 0; sobel_x[0][2] =1; 219 | sobel_x[1][0] = -2; sobel_x[1][1] = 0; sobel_x[1][2] =2; 220 | sobel_x[2][0] = -1; sobel_x[2][1] = 0; sobel_x[2][2] =1; 221 | // asigning values to sobel y direction 222 | sobel_y[0][0] = -1; sobel_y[0][1] = -2; sobel_y[0][2] = -1; 223 | sobel_y[1][0] = 0; sobel_y[1][1] = 0; sobel_y[1][2] = 0; 224 | sobel_y[2][0] = 1; sobel_y[2][1] = 2; sobel_y[2][2] = 1; 225 | printf(" picture size is %d x %d \n", g_imgHeight, g_imgWidth); 226 | //高斯滤波 227 | GaussianBlur(g_grayImage, g_gaussImage, Size(3,3), 0, 0, BORDER_DEFAULT); 228 | cvNamedWindow("gaussimage", 0); 229 | resizeWindow("gaussimage", 800, 600); 230 | imshow("gaussimage", g_gaussImage); 231 | } 232 | /** 233 | *@author:Seafood 234 | *@name:sobelGPUPixel() 235 | *@return:void 236 | *@function:调用GPU对图像处理并计算时间 237 | *@para:None 238 | *其他要注意的地方 239 | **/ 240 | //GPU处理函数 241 | void sobelGPUPixel() 242 | { 243 | //定义变量 244 | unsigned char *dev_in; 245 | unsigned char *dev_out; 246 | 247 | Mat dst_Gpu(g_imgHeight, g_imgWidth, CV_8UC1, Scalar(0)); 248 | //创建时间用于计算 249 | cudaEvent_t start, stop; 250 | cudaEventCreate( &start ); 251 | cudaEventCreate( &stop ); 252 | //开始时间点记录 253 | cudaEventRecord( start, 0 ); 254 | 255 | 256 | 257 | //定义数组 258 | //申请内存 259 | cudaMalloc((void**)&dev_in, g_imgHeight * g_imgWidth * sizeof(unsigned char)); 260 | cudaMalloc((void**)&dev_out, g_imgHeight * g_imgWidth * sizeof(unsigned char)); 261 | //纹理内存绑定 262 | cudaBindTexture(NULL, texIn, dev_in, g_imgHeight * g_imgWidth * sizeof(unsigned char)); 263 | //导入内存 264 | cudaMemcpy(dev_in, g_gaussImage.data, g_imgHeight * g_imgWidth * sizeof(unsigned char), cudaMemcpyHostToDevice); 265 | 266 | //数组导入 267 | cudaMemcpyToSymbol(dev_sobel_x, sobel_x, sizeof(sobel_x) ); 268 | cudaMemcpyToSymbol(dev_sobel_y, sobel_y, sizeof(sobel_y) ); 269 | 270 | //调用核函数 271 | //定义block thread范围 272 | dim3 blocks((int)((g_imgWidth+31)/32), (int)(g_imgHeight+31)/32); 273 | //dim3 blocks(4, 4); 274 | dim3 threads(16, 16); 275 | //单block 单thread 276 | sobelInCuda<<<4,4>> >(dev_out, g_imgHeight, g_imgWidth); 277 | 278 | //导出处理 279 | cudaMemcpy(dst_Gpu.data, dev_out, g_imgHeight * g_imgWidth * sizeof(unsigned char), cudaMemcpyDeviceToHost); 280 | 281 | //停止时间点 282 | cudaEventRecord( stop, 0 ); 283 | cudaEventSynchronize( stop ); 284 | 285 | //释放内存 286 | cudaFree(dev_in); 287 | cudaFree(dev_out); 288 | cudaFree(dev_sobel_x); 289 | cudaFree(dev_sobel_y); 290 | 291 | 292 | //计算GPU所用时间 293 | float elapsedTime; 294 | cudaEventElapsedTime( &elapsedTime, start, stop ); 295 | printf( "GPU对像素操作运行时间为: %.1f ms \n", elapsedTime ); 296 | cudaEventDestroy( start ); 297 | cudaEventDestroy( stop ); 298 | 299 | //显示处理后的图像 300 | cvNamedWindow("GPU处理后的图像", 0); 301 | resizeWindow("GPU处理后的图像", 800, 600); 302 | imshow("GPU处理后的图像", dst_Gpu); 303 | } 304 | /** 305 | *@author:Seafood 306 | *@name:main(int argc, char *argv[], char **env) 307 | *@return:int 308 | *@function:程序入口,主函数 309 | *@para:None 310 | *其他要注意的地方 311 | **/ 312 | //main函数 313 | int main(int argc, char *argv[], char **env) 314 | { 315 | 316 | //图像读入和处理 317 | pictureInit(); 318 | //Sobel算子Cpu package实现 319 | 320 | sobelCpuPackage(0,0); 321 | 322 | //测试算子 323 | //Sobel算子Cpu 对像素操作实现 324 | sobelCpuPixel(); 325 | 326 | //Sobel算子GPU操作实现 327 | sobelGPUPixel(); 328 | //结束展示 329 | while((char)waitKey(0) != 'q' ) 330 | { 331 | 332 | } 333 | 334 | return 0; 335 | } --------------------------------------------------------------------------------