cuda实践之sobel边缘检测实现
2017-08-15 11:05
323 查看
1. Sobel算法
Sobel是一个离散的一阶差分算子,用来计算图像亮度函数的一阶梯度之近似值。在图像的任何一点使用此算子,将会产生该点对应的梯度矢量或是其法矢量该算子包含两组3x3的矩阵,分别为横向及纵向,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。如果以A代表原始图像,Gx及Gy分别代表经横向及纵向边缘检测的图像,其公式如下:
图像的每一个像素的横向及纵向梯度近似值可用以下的公式结合,来计算梯度的大小:
可用以下公式计算梯度方向:
2.cuda编程实现:
1.sobel.hpp文件#include<opencv2/opencv.hpp> void sobel_func(uchar *img,uchar *sobel);
2.sobel.cu文件
#include <cuda_runtime.h> #include <stdio.h> #include <stdlib.h> #include <math.h> #include <opencv2/opencv.hpp> #include "sobel.hpp" //此处本例程处理的图片大小为640x480 const int W =640; const int H =480; uchar *cuda_sobelin,*cuda_sobel; __device__ int sobel_gpu(uchar a, uchar b, uchar c, uchar d, uchar e, uchar f){ return ((a + 2*b + c) - (d + 2*e + f)); } void setCudaDevice(int devNum) { cudaDeviceProp devProp; cudaGetDeviceProperties(&devProp, devNum); cudaSetDevice(devNum); } //核函数 __global__ void sobel_gpu(uchar * img_in, uchar * img_out,int img_w, int img_h) { int row = blockDim.y * blockIdx.y + threadIdx.y; int col = blockDim.x * blockIdx.x + threadIdx.x; if((row >= 1) && (row < (img_h-1)) && (col >= 1) && (col < (img_w-1))) { uchar x1, x2, x3, x4, x6, x7, x8,x9; x1=img_in[(row-1)*img_w+(col-1)]; x2=img_in[(row-1)*img_w+col]; x3=img_in[(row-1)*img_w+col+1]; x4=img_in[row*img_w+col-1]; x6=img_in[row*img_w+col+1]; x7=img_in[(row+1)*img_w+col-1]; x8=img_in[(row+1)*img_w+col]; x9=img_in[(row+1)*img_w+col+1]; int dfdy= sobel_gpu(x1, x2, x3, x7, x8, x9); int dfdx= sobel_gpu(x1, x4, x7, x3, x6, x9); int gradient= sqrtf(dfdy*dfdy+dfdx*dfdx); img_out[row*img_w+col] = gradient; } } void sobel_func(uchar *img,uchar *sobelout) { setCudaDevice(0); cudaMalloc((void**)&cuda_sobelin, sizeof(uchar)* W*H); cudaMalloc((void**)&cuda_sobel, sizeof(uchar)* W*H); cudaMemcpy(cuda_sobelin, img, sizeof(uchar)* W * H, cudaMemcpyHostToDevice); dim3 threadsPerBlock(16,16); dim3 blocksPerGrid((W+15)/16,(H+15)/16); sobel_gpu<<<blocksPerGrid,threadsPerBlock>>>(cuda_sobelin,cuda_sobel,W,H); cudaThreadSynchronize(); cudaMemcpy(sobelout, cuda_sobel, sizeof(uchar)* W * H, cudaMemcpyDeviceToHost); }
3.main.cpp文件
#include <stdio.h> #include <stdlib.h> #include <math.h> #include <iostream> #include <opencv2/opencv.hpp> #include "sobel.hpp" using namespace cv; using namespace std; int main() { Mat detect_img=imread("detect_img.jpg"); //resize到640x480大小再处理 cv::resize(detect_img, detect_img, cv::Size(640, 480), (0, 0), (0, 0), cv::INTER_LINEAR); cvtColor(detect_img,detect_imggray,CV_BGR2GRAY); //cuda实现 if(detect_imggray.isContinuous()) sobelin=detect_imggray.data; sobel_func(sobelin,sobelout); Mat sobel(480,640,CV_8UC1,(uchar*)sobelout); imshow("sobel",sobel); //opencv函数Sobel实现 Mat grad_x, grad_y; Mat abs_grad_x, abs_grad_y; Sobel( detect_imggray, grad_x, CV_16S, 1, 0, 3, 1, 0, BORDER_DEFAULT ); convertScaleAbs( grad_x, abs_grad_x ); Sobel( detect_imggray, grad_y, CV_16S, 0, 1, 3, 1, 0, BORDER_DEFAULT ); convertScaleAbs( grad_y, abs_grad_y ); Mat sobel1; addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, sobel1); imshow("opencv",sobel1); waitKey(1); }
相关文章推荐
- 【cuda学习笔记】2.纹理对象API的使用,实现sobel边缘检测
- 基于MATLAB的Sobel边缘检测算法实现
- Unity之梯度应用实现Roberts、Prewitt、Sobel边缘检测
- Sobel边缘检测的OpenCV实现
- 我的CUDA学习之旅4——Sobel算子图像边缘检测CUDA实现
- 第六节--基于Sobel的边缘检测C++程序的实现
- OpenCV,三大边缘检测Canny,Sobel,Laplacian,及MFC实现
- 数字集成电路设计-8-一个简单sobel图像边缘检测加速器的设计,实现,仿真与综合
- 基于FPGA的Sobel边缘检测的实现
- 图像sobel、laplacian、canny边缘检测算法基础实现
- OpenCV-基本边缘检测算子Sobel实现
- opencv实践程序4——canny实现摄像头的边缘检测,高斯背景建模
- OpenCV使用Sobel滤波器实现图像边缘检测
- 数字集成电路设计-8-一个简单sobel图像边缘检测加速器的设计,实现,仿真与综合
- OpenCV之imgproc 模块. 图像处理(2)实现自己的线性滤波器 给图像添加边界 Sobel 导数 Laplace 算子 Canny 边缘检测
- opencv实现sobel边缘检测
- Canny边缘检测算法原理及其VC实现
- opencv+vs2008实现canny边缘检测与hough变换检测直线并用红线在原图标出直线
- Sobel边缘检测算法
- Canny边缘检测算法原理及其VC实现详解(二)