|
|
|
@ -46,128 +46,73 @@ |
|
|
|
|
namespace cv |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
void spatialGradient( InputArray _src, OutputArray _dx, OutputArray _dy, int ksize ) |
|
|
|
|
void spatialGradient( InputArray _src, OutputArray _dx, OutputArray _dy, |
|
|
|
|
int ksize, int borderType ) |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
// Prepare InputArray src
|
|
|
|
|
Mat src = _src.getMat(); |
|
|
|
|
CV_Assert( !src.empty() ); |
|
|
|
|
CV_Assert( src.isContinuous() ); |
|
|
|
|
CV_Assert( src.type() == CV_8UC1 ); |
|
|
|
|
CV_Assert( borderType == BORDER_DEFAULT || borderType == BORDER_REPLICATE ); |
|
|
|
|
|
|
|
|
|
// Prepare OutputArrays dx, dy
|
|
|
|
|
_dx.create( src.size(), CV_16SC1 ); |
|
|
|
|
_dy.create( src.size(), CV_16SC1 ); |
|
|
|
|
Mat dx = _dx.getMat(), |
|
|
|
|
dy = _dy.getMat(); |
|
|
|
|
CV_Assert( dx.isContinuous() ); |
|
|
|
|
CV_Assert( dy.isContinuous() ); |
|
|
|
|
|
|
|
|
|
// TODO: Allow for other kernel sizes
|
|
|
|
|
CV_Assert(ksize == 3); |
|
|
|
|
|
|
|
|
|
// Reference
|
|
|
|
|
//Sobel( src, dx, CV_16SC1, 1, 0, ksize );
|
|
|
|
|
//Sobel( src, dy, CV_16SC1, 0, 1, ksize );
|
|
|
|
|
|
|
|
|
|
// Get dimensions
|
|
|
|
|
int H = src.rows, |
|
|
|
|
W = src.cols, |
|
|
|
|
N = H * W; |
|
|
|
|
|
|
|
|
|
// Get raw pointers to input/output data
|
|
|
|
|
uchar* p_src = src.ptr<uchar>(0); |
|
|
|
|
short* p_dx = dx.ptr<short>(0); |
|
|
|
|
short* p_dy = dy.ptr<short>(0); |
|
|
|
|
const int H = src.rows, |
|
|
|
|
W = src.cols; |
|
|
|
|
|
|
|
|
|
// Row, column indices
|
|
|
|
|
int i, j; |
|
|
|
|
|
|
|
|
|
/* NOTE:
|
|
|
|
|
* |
|
|
|
|
* Sobel-x: -1 0 1 |
|
|
|
|
* -2 0 2 |
|
|
|
|
* -1 0 1 |
|
|
|
|
* |
|
|
|
|
* Sobel-y: -1 -2 -1 |
|
|
|
|
* 0 0 0 |
|
|
|
|
* 1 2 1 |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
// No-SSE
|
|
|
|
|
int idx; |
|
|
|
|
// Store pointers to rows of input/output data
|
|
|
|
|
// Padded by two rows for border handling
|
|
|
|
|
uchar* P_src[H+2]; |
|
|
|
|
short* P_dx [H+2]; |
|
|
|
|
short* P_dy [H+2]; |
|
|
|
|
|
|
|
|
|
p_dx[0] = 0; // Top-left corner
|
|
|
|
|
p_dy[0] = 0; |
|
|
|
|
p_dx[W-1] = 0; // Top-right corner
|
|
|
|
|
p_dy[W-1] = 0; |
|
|
|
|
p_dx[N-1] = 0; // Bottom-right corner
|
|
|
|
|
p_dy[N-1] = 0; |
|
|
|
|
p_dx[N-W] = 0; // Bottom-left corner
|
|
|
|
|
p_dy[N-W] = 0; |
|
|
|
|
int i_top = 0, // Case for H == 1 && W == 1 && BORDER_REPLICATE
|
|
|
|
|
i_bottom = H - 1, |
|
|
|
|
j_offl = 0, // j offset from 0th pixel to reach -1st pixel
|
|
|
|
|
j_offr = 0; // j offset from W-1th pixel to reach Wth pixel
|
|
|
|
|
|
|
|
|
|
// Handle special case: column matrix
|
|
|
|
|
if ( W == 1 ) |
|
|
|
|
if ( borderType == BORDER_DEFAULT ) // Equiv. to BORDER_REFLECT_101
|
|
|
|
|
{ |
|
|
|
|
for ( i = 1; i < H - 1; i++ ) |
|
|
|
|
if ( H > 1 ) |
|
|
|
|
{ |
|
|
|
|
p_dx[i] = 0; |
|
|
|
|
p_dy[i] = 4*(p_src[i + 1] - p_src[i - 1]); // Should be 2?! 4 makes tests pass
|
|
|
|
|
i_top = 1; |
|
|
|
|
i_bottom = H - 2; |
|
|
|
|
} |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Handle special case: row matrix
|
|
|
|
|
if ( H == 1 ) |
|
|
|
|
{ |
|
|
|
|
for ( j = 1; j < W - 1; j++ ) |
|
|
|
|
if ( W > 1 ) |
|
|
|
|
{ |
|
|
|
|
p_dx[j] = 4*(p_src[j + 1] - p_src[j - 1]); // Should be 2?! 4 makes tests pass
|
|
|
|
|
p_dy[j] = 0; |
|
|
|
|
j_offl = 1; |
|
|
|
|
j_offr = -1; |
|
|
|
|
} |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Do top row
|
|
|
|
|
for ( j = 1; j < W - 1; j++ ) |
|
|
|
|
{ |
|
|
|
|
idx = j; |
|
|
|
|
p_dx[idx] = -(p_src[idx+W-1] + 2*p_src[idx-1] + p_src[idx+W-1]) + |
|
|
|
|
(p_src[idx+W+1] + 2*p_src[idx+1] + p_src[idx+W+1]); |
|
|
|
|
p_dy[idx] = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Do right column
|
|
|
|
|
idx = 2*W - 1; |
|
|
|
|
for ( i = 1; i < H - 1; i++ ) |
|
|
|
|
{ |
|
|
|
|
p_dx[idx] = 0; |
|
|
|
|
p_dy[idx] = -(p_src[idx-W-1] + 2*p_src[idx-W] + p_src[idx-W-1]) + |
|
|
|
|
(p_src[idx+W-1] + 2*p_src[idx+W] + p_src[idx+W-1]); |
|
|
|
|
idx += W; |
|
|
|
|
} |
|
|
|
|
P_src[0] = src.ptr<uchar>(i_top); // Mirrored top border
|
|
|
|
|
P_src[H+1] = src.ptr<uchar>(i_bottom); // Mirrored bottom border
|
|
|
|
|
|
|
|
|
|
// Do bottom row
|
|
|
|
|
idx = N - W + 1; |
|
|
|
|
for ( j = 1; j < W - 1; j++ ) |
|
|
|
|
for ( i = 0; i < H; i++ ) |
|
|
|
|
{ |
|
|
|
|
p_dx[idx] = -(p_src[idx-W-1] + 2*p_src[idx-1] + p_src[idx-W-1]) + |
|
|
|
|
(p_src[idx-W+1] + 2*p_src[idx+1] + p_src[idx-W+1]); |
|
|
|
|
p_dy[idx] = 0; |
|
|
|
|
idx++; |
|
|
|
|
P_src[i+1] = src.ptr<uchar>(i); |
|
|
|
|
P_dx [i] = dx.ptr<short>(i); |
|
|
|
|
P_dy [i] = dy.ptr<short>(i); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Do left column
|
|
|
|
|
idx = W; |
|
|
|
|
for ( i = 1; i < H - 1; i++ ) |
|
|
|
|
{ |
|
|
|
|
p_dx[idx] = 0; |
|
|
|
|
p_dy[idx] = -(p_src[idx-W+1] + 2*p_src[idx-W] + p_src[idx-W+1]) + |
|
|
|
|
(p_src[idx+W+1] + 2*p_src[idx+W] + p_src[idx+W+1]); |
|
|
|
|
idx += W; |
|
|
|
|
} |
|
|
|
|
// Pointer to row vectors
|
|
|
|
|
uchar *p_src, *c_src, *n_src; // previous, current, next row
|
|
|
|
|
short *c_dx, *c_dy; |
|
|
|
|
|
|
|
|
|
// Do Inner area
|
|
|
|
|
int j_start = 0; |
|
|
|
|
/*
|
|
|
|
|
#if CV_SIMD128 |
|
|
|
|
// Characters in variable names have the following meanings:
|
|
|
|
|
// u: unsigned char
|
|
|
|
@ -260,16 +205,39 @@ void spatialGradient( InputArray _src, OutputArray _dx, OutputArray _dy, int ksi |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#else |
|
|
|
|
for ( i = 1; i < H - 1; i++ ) |
|
|
|
|
for ( j = 1; j < W - 1; j++ ) |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
/* NOTE:
|
|
|
|
|
* |
|
|
|
|
* Sobel-x: -1 0 1 |
|
|
|
|
* -2 0 2 |
|
|
|
|
* -1 0 1 |
|
|
|
|
* |
|
|
|
|
* Sobel-y: -1 -2 -1 |
|
|
|
|
* 0 0 0 |
|
|
|
|
* 1 2 1 |
|
|
|
|
*/ |
|
|
|
|
int j_p, j_n; |
|
|
|
|
for ( i = 0; i < H; i++ ) |
|
|
|
|
{ |
|
|
|
|
idx = i*W + j; |
|
|
|
|
p_dx[idx] = -(p_src[idx-W-1] + 2*p_src[idx-1] + p_src[idx+W-1]) + |
|
|
|
|
(p_src[idx-W+1] + 2*p_src[idx+1] + p_src[idx+W+1]); |
|
|
|
|
p_dy[idx] = -(p_src[idx-W-1] + 2*p_src[idx-W] + p_src[idx-W+1]) + |
|
|
|
|
(p_src[idx+W-1] + 2*p_src[idx+W] + p_src[idx+W+1]); |
|
|
|
|
p_src = P_src[i]; c_src = P_src[i+1]; n_src = P_src[i+2]; |
|
|
|
|
c_dx = P_dx [i]; |
|
|
|
|
c_dy = P_dy [i]; |
|
|
|
|
|
|
|
|
|
for ( j = j_start; j < W; j++ ) |
|
|
|
|
{ |
|
|
|
|
j_p = j - 1; |
|
|
|
|
j_n = j + 1; |
|
|
|
|
if ( j_p < 0 ) j_p = j + j_offl; |
|
|
|
|
if ( j_n >= W ) j_n = j + j_offr; |
|
|
|
|
|
|
|
|
|
c_dx[j] = -(p_src[j_p] + c_src[j_p] + c_src[j_p] + n_src[j_p]) + |
|
|
|
|
(p_src[j_n] + c_src[j_n] + c_src[j_n] + n_src[j_n]); |
|
|
|
|
c_dy[j] = -(p_src[j_p] + p_src[j] + p_src[j] + p_src[j_n]) + |
|
|
|
|
(n_src[j_p] + n_src[j] + n_src[j] + n_src[j_n]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
//#endif
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|