Files
feature-extraction-opencl/kernel/freak.cl
T
2021-08-23 15:35:30 +02:00

129 lines
5.5 KiB
Common Lisp

void meanIntensity( image2d_t _image, image2d_t _integral, float kp_x, float kp_y,
int scale, int rot, int* point, float3* patternLookupPtr, uchar* output)
{
// Prepare a suitable OpenCL image sampler.
sampler_t const sampler = CLK_ADDRESS_CLAMP | CLK_FILTER_NEAREST;
// get point position in image
float3* FreakPoint = patternLookupPtr + (scale * FREAK_NB_ORIENTATION * FREAK_NB_POINTS + rot * FREAK_NB_POINTS + (*point));
float xf = FreakPoint->x + kp_x;
float yf = FreakPoint->y + kp_y;
int x = (int)xf;
int y = (int)yf;
// get the sigma:
float radius = FreakPoint->z;//sigma
// calculate output:
if( radius < 0.5 )
{
// interpolation multipliers:
const int r_x = (int)((xf - x) * 1024);
const int r_y = (int)((yf - y) * 1024);
const int r_x_1 = (1024 - r_x);
const int r_y_1 = (1024 - r_y);
uint ret_val;
// linear interpolation:
ret_val = (r_x_1 * r_y_1 * (int)(read_imageui(_image, sampler, (int2)(y , x ))).x)
+ (r_x * r_y_1 * (int)(read_imageui(_image, sampler, (int2)(y , x+1))).x)
+ (r_x_1 * r_y * (int)(read_imageui(_image, sampler, (int2)(y+1, x ))).x)
+ (r_x * r_y * (int)(read_imageui(_image, sampler, (int2)(y+1, x+1))).x);
// return the rounded mean
ret_val += 2 * 1024 * 1024;
output[*point] = (uchar)(ret_val / (4 * 1024 * 1024));
}
// calculate borders
const int x_left = round(xf - radius);
const int y_top = round(yf - radius);
const int x_right = round(xf + radius + 1); // integral image is 1px wider
const int y_bottom = round(yf + radius + 1); // integral image is 1px higher
int ret_val;
ret_val = read_imageui(_integral, sampler, (int2)(y_bottom, x_right)).x; // bottom right corner
ret_val -= read_imageui(_integral, sampler, (int2)(y_bottom, x_left)).x; // bottom left corner
ret_val += read_imageui(_integral, sampler, (int2)(y_top, x_left)).x; // top left corner
ret_val -= read_imageui(_integral, sampler, (int2)(y_top, x_right)).x; // top right corner
const int area = (x_right - x_left) * (y_bottom - y_top);
ret_val = (ret_val + area / 2) / area;
output[*point] = (uchar)(ret_val);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
__kernel void freak(
__read_only image2d_t image, // grayescale image
__read_only image2d_t imgIntegral,
__global float3* keypoints, // ptx, pty, angle
__global uchar* descriptors, // kp_size * (64 = NB_PAIRS/8) - CV_8U with zero values
__global int* patternSizes, // array size : NB_SCALES = 64
__global int4* orientationPairs, // array size : FREAK_NB_ORIENTATION = 256
__global float3* patternLookup, // array size : NB_SCALES(64) * FREAK_NB_ORIENTATION(256) * FREAK_NB_POINTS(43)
__global uchar2* descriptionPairs, // array size : NB_PAIRS = 512
__global int* nOctaves,
__global int* kpScaleIdx //array size = kp_size - used to save pattern scale index corresponding to each keypoints
)
{
const float sizeCst = (float)(NB_SCALES / (FREAK_LOG2 * *nOctaves));
uchar pointsValue[FREAK_NB_POINTS];
int thetaIdx = 0;
int direction0;
int direction1;
int k = get_global_id(0);
kpScaleIdx[k] = max( (int)(log(7.0 / FREAK_SMALLEST_KP_SIZE) * sizeCst + 0.5) ,0);
if( kpScaleIdx[k] >= NB_SCALES )
kpScaleIdx[k] = NB_SCALES - 1;
if( keypoints[k].x <= patternSizes[kpScaleIdx[k]] || // check if the description at this specific position and scale fits inside the image
keypoints[k].y <= patternSizes[kpScaleIdx[k]] ||
keypoints[k].x >= get_image_dim(image).y - patternSizes[kpScaleIdx[k]] ||
keypoints[k].y >= get_image_dim(image).x - patternSizes[kpScaleIdx[k]])
return;
// get the points intensity value in the un-rotated pattern
for( int i = FREAK_NB_POINTS; i--; )
{
meanIntensity(image, imgIntegral, keypoints[k].x, keypoints[k].y,
*(kpScaleIdx + k), 0, &i, patternLookup, pointsValue);
}
direction0 = 0;
direction1 = 0;
for( int m = 45; m--; )
{
// iterate through the orientation pairs
const int delta = (pointsValue[ orientationPairs[m].w ] - pointsValue[ orientationPairs[m].x ]);
direction0 += delta * (orientationPairs[m].y) / 2048; // weight_dx
direction1 += delta * (orientationPairs[m].z) / 2048; // weight_dy
}
thetaIdx = round(FREAK_NB_ORIENTATION *
(float)(atan2((float)direction1,(float)direction0) * (180.0 / 3.141592653589793238462643383279502884197169399375)) *
(1 / 360.0));
if( thetaIdx < 0 )
thetaIdx += FREAK_NB_ORIENTATION;
if( thetaIdx >= FREAK_NB_ORIENTATION )
thetaIdx -= FREAK_NB_ORIENTATION;
// extract descriptor at the computed orientation
for( int i = FREAK_NB_POINTS; i--; )
{
meanIntensity(image, imgIntegral, keypoints[k].x, keypoints[k].y,
*(kpScaleIdx + k), thetaIdx, &i, patternLookup, pointsValue);
}
// Extract descriptor
int cnt = 0;
for( int n = 0; n<4; n++ )
{
for (int m = 8; m >= 1; m--)
{
for(int kk = (n*16)+15; kk >= (n*16); --kk, ++cnt)
{
descriptors[(k * 64) + kk] *= 2;
if (pointsValue[(int)descriptionPairs[cnt].x] >= pointsValue[(int)descriptionPairs[cnt].y])
descriptors[(k * 64) + kk] += 1;
}
}
}
}