mirror of
https://github.com/opencv/opencv.git
synced 2026-07-29 15:23:05 +04:00
implemented brute force convolve for small kernel sizes
This commit is contained in:
@@ -951,6 +951,84 @@ namespace cv { namespace gpu { namespace imgproc
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// convolve
|
||||
|
||||
#define CONVOLVE_MAX_KERNEL_SIZE 17
|
||||
|
||||
__constant__ float c_convolveKernel[CONVOLVE_MAX_KERNEL_SIZE * CONVOLVE_MAX_KERNEL_SIZE];
|
||||
|
||||
__global__ void convolve(const DevMem2Df src, PtrStepf dst, int kWidth, int kHeight)
|
||||
{
|
||||
__shared__ float smem[16 + 2 * 8][16 + 2 * 8];
|
||||
|
||||
const int x = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
const int y = blockIdx.y * blockDim.y + threadIdx.y;
|
||||
|
||||
// x | x 0 | 0
|
||||
// -----------
|
||||
// x | x 0 | 0
|
||||
// 0 | 0 0 | 0
|
||||
// -----------
|
||||
// 0 | 0 0 | 0
|
||||
smem[threadIdx.y][threadIdx.x] = src.ptr(min(max(y - 8, 0), src.rows - 1))[min(max(x - 8, 0), src.cols - 1)];
|
||||
|
||||
// 0 | 0 x | x
|
||||
// -----------
|
||||
// 0 | 0 x | x
|
||||
// 0 | 0 0 | 0
|
||||
// -----------
|
||||
// 0 | 0 0 | 0
|
||||
smem[threadIdx.y][threadIdx.x + 16] = src.ptr(min(max(y - 8, 0), src.rows - 1))[min(x + 8, src.cols - 1)];
|
||||
|
||||
// 0 | 0 0 | 0
|
||||
// -----------
|
||||
// 0 | 0 0 | 0
|
||||
// x | x 0 | 0
|
||||
// -----------
|
||||
// x | x 0 | 0
|
||||
smem[threadIdx.y + 16][threadIdx.x] = src.ptr(min(y + 8, src.rows - 1))[min(max(x - 8, 0), src.cols - 1)];
|
||||
|
||||
// 0 | 0 0 | 0
|
||||
// -----------
|
||||
// 0 | 0 0 | 0
|
||||
// 0 | 0 x | x
|
||||
// -----------
|
||||
// 0 | 0 x | x
|
||||
smem[threadIdx.y + 16][threadIdx.x + 16] = src.ptr(min(y + 8, src.rows - 1))[min(x + 8, src.cols - 1)];
|
||||
|
||||
__syncthreads();
|
||||
|
||||
if (x < src.cols && y < src.rows)
|
||||
{
|
||||
float res = 0;
|
||||
|
||||
for (int i = 0; i < kHeight; ++i)
|
||||
{
|
||||
for (int j = 0; j < kWidth; ++j)
|
||||
{
|
||||
res += smem[threadIdx.y + 8 - kHeight / 2 + i][threadIdx.x + 8 - kWidth / 2 + j] * c_convolveKernel[i * kWidth + j];
|
||||
}
|
||||
}
|
||||
|
||||
dst.ptr(y)[x] = res;
|
||||
}
|
||||
}
|
||||
|
||||
void convolve_gpu(const DevMem2Df& src, const PtrStepf& dst, int kWidth, int kHeight, float* kernel)
|
||||
{
|
||||
cudaSafeCall(cudaMemcpyToSymbol(c_convolveKernel, kernel, kWidth * kHeight * sizeof(float), 0, cudaMemcpyDeviceToDevice) );
|
||||
|
||||
const dim3 block(16, 16);
|
||||
const dim3 grid(divUp(src.cols, block.x), divUp(src.rows, block.y));
|
||||
|
||||
convolve<<<grid, block>>>(src, dst, kWidth, kHeight);
|
||||
cudaSafeCall(cudaGetLastError());
|
||||
|
||||
cudaSafeCall(cudaDeviceSynchronize());
|
||||
}
|
||||
|
||||
|
||||
}}}
|
||||
|
||||
|
||||
|
||||
@@ -1576,6 +1576,10 @@ void cv::gpu::convolve(const GpuMat& image, const GpuMat& templ, GpuMat& result,
|
||||
convolve(image, templ, result, ccorr, buf);
|
||||
}
|
||||
|
||||
namespace cv { namespace gpu { namespace imgproc
|
||||
{
|
||||
void convolve_gpu(const DevMem2Df& src, const PtrStepf& dst, int kWidth, int kHeight, float* kernel);
|
||||
}}}
|
||||
|
||||
void cv::gpu::convolve(const GpuMat& image, const GpuMat& templ, GpuMat& result,
|
||||
bool ccorr, ConvolveBuf& buf)
|
||||
@@ -1586,6 +1590,24 @@ void cv::gpu::convolve(const GpuMat& image, const GpuMat& templ, GpuMat& result,
|
||||
CV_Assert(image.type() == CV_32F);
|
||||
CV_Assert(templ.type() == CV_32F);
|
||||
|
||||
if (templ.cols < 13 && templ.rows < 13)
|
||||
{
|
||||
result.create(image.size(), CV_32F);
|
||||
GpuMat contKernel;
|
||||
|
||||
if (templ.isContinuous())
|
||||
contKernel = templ;
|
||||
else
|
||||
{
|
||||
contKernel = createContinuous(templ.size(), templ.type());
|
||||
templ.copyTo(contKernel);
|
||||
}
|
||||
|
||||
imgproc::convolve_gpu(image, result, templ.cols, templ.rows, contKernel.ptr<float>());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
buf.create(image.size(), templ.size());
|
||||
result.create(buf.result_size, CV_32F);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user