-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathproject_kernel.cl
More file actions
201 lines (176 loc) · 8.91 KB
/
project_kernel.cl
File metadata and controls
201 lines (176 loc) · 8.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
// Jaakko Astikainen 2024
#include "project.h"
__kernel void downsample(__read_only image2d_t image,
unsigned width,
unsigned height,
unsigned new_width,
unsigned new_height,
__write_only image2d_t resized_image)
{
// Get global ID in 2D
unsigned int x = get_global_id(0); // Column index
unsigned int y = get_global_id(1); // Row index
if (x < new_width && y < new_height) {
// Read pixel value from the original image
uint4 pixel = read_imageui(image, CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP_TO_EDGE, (int2)(x * DOWN_RATIO, y * DOWN_RATIO));
// Write pixel value to the resized image
write_imageui(resized_image, (int2)(x, y), pixel);
}
}
__kernel void to_grayscale(__read_only image2d_t image,
unsigned width,
unsigned height,
__global uchar* gray_image)
{
// Get global ID in 2D
int x = get_global_id(0);
int y = get_global_id(1);
if (x < width && y < height) {
// Read pixel value from the input image
int2 coords = (int2)(x, y);
uint4 pixel = read_imageui(image, coords);
// Convert RGB to grayscale using luminance formula
uchar gray = (uchar)(0.2126f * pixel.x + 0.7152f * pixel.y + 0.0722f * pixel.z);
// Calculate index for accessing the pixel in the output image
int index = y * width + x;
// Store grayscale value in the output buffer
gray_image[index] = gray;
}
}
__kernel void compute_disparity_map(__global uchar* left_image,
__global uchar* right_image,
uint width,
uint height,
int direction,
uint scaled_ndisp,
__global uchar* disparity_map)
{
// Get global indices
uint x = get_global_id(0);
uint y = get_global_id(1);
// Ensure the thread processes a valid pixel
if (x < width && y < height) {
int kernel_radius = KERNEL_SIZE / 2;
int best_disparity = 0;
float best_zncc = -1;
// Adjust stereo matching direction based on input parameter
int start_disparity = 0;//(direction == 0) ? 0 : scaled_ndisp - 1;
int end_disparity = scaled_ndisp;//(direction == 0) ? scaled_ndisp : -1;
int step = 1;//(direction == 0) ? 1 : -1;
// Iterate over disparities
for (int d = start_disparity; d != end_disparity; d += step) {
// Check if the current disparity allows the kernel to fit within the image boundaries
if (((!direction && x >= kernel_radius + d) || (direction && x >= kernel_radius)) && ((!direction && x < width - kernel_radius ) || (direction && x < width - kernel_radius - d)) && y >= kernel_radius && y < height - kernel_radius) {
// Extract patches from left and right images
uchar left_patch[KERNEL_SIZE * KERNEL_SIZE];
uchar right_patch[KERNEL_SIZE * KERNEL_SIZE];
for (int i = 0; i < KERNEL_SIZE; i++) {
for (int j = 0; j < KERNEL_SIZE; j++) {
int left_x = x - kernel_radius + j;
int left_y = y - kernel_radius + i;
int right_x = direction ? x - kernel_radius + j + d : x - kernel_radius + j - d;
int right_y = y - kernel_radius + i;
left_patch[i * KERNEL_SIZE + j] = left_image[left_y * width + left_x];
right_patch[i * KERNEL_SIZE + j] = right_image[right_y * width + right_x];
}
}
// Compute ZNCC score
float mean_left = 0, mean_right = 0, std_left = 0, std_right = 0, cross_corr = 0;
for (int i = 0; i < KERNEL_SIZE * KERNEL_SIZE; i++) {
mean_left += left_patch[i];
mean_right += right_patch[i];
}
mean_left /= (KERNEL_SIZE * KERNEL_SIZE);
mean_right /= (KERNEL_SIZE * KERNEL_SIZE);
for (int i = 0; i < KERNEL_SIZE * KERNEL_SIZE; i++) {
float diff_left = left_patch[i] - mean_left;
float diff_right = right_patch[i] - mean_right;
std_left += diff_left * diff_left;
std_right += diff_right * diff_right;
cross_corr += diff_left * diff_right;
}
std_left = sqrt(std_left / (KERNEL_SIZE * KERNEL_SIZE));
std_right = sqrt(std_right / (KERNEL_SIZE * KERNEL_SIZE));
float zncc = cross_corr / (std_left * std_right);
// Update best disparity if needed
if (zncc > best_zncc) {
best_zncc = zncc;
best_disparity = d;
}
}
}
// Normalize disparity value to the range of 0-255
// disparity_map[y * width + x] = (uchar)((best_disparity * 255) / scaled_ndisp);
disparity_map[y * width + x] = (uchar)(best_disparity);
}
}
__kernel void cross_checking(__global uchar* left_disparity_map,
__global uchar* right_disparity_map,
__global uchar* consolidated_disparity_map,
const unsigned width,
const unsigned height,
const unsigned threshold,
uint scaled_ndisp) {
// Get the global ID in 2D
const unsigned int x = get_global_id(0);
const unsigned int y = get_global_id(1);
// Calculate the index in the flattened array
const unsigned int index = y * width + x;
// Check if within bounds
if (x < width && y < height) {
// Perform cross-checking logic
if ((int)(abs(left_disparity_map[index] - right_disparity_map[index - left_disparity_map[index]]))*255/scaled_ndisp > threshold) {
// If the absolute difference is larger than the threshold, set the pixel value to zero
consolidated_disparity_map[index] = 0;
} else {
// Otherwise, retain the pixel value from the left disparity map
consolidated_disparity_map[index] = (uchar)(((int)left_disparity_map[index])*255/scaled_ndisp);
}
}
}
__kernel void occlusion_filling(__global uchar* disparity_map,
__global uchar* occlusion_map,
const unsigned int width,
const unsigned int height,
const int max_radius)
{
const unsigned int x = get_global_id(0);
const unsigned int y = get_global_id(1);
if (x < width && y < height) {
// Get the current pixel index
const unsigned int index = y * width + x;
occlusion_map[index] = disparity_map[index];
// Check if the current pixel needs occlusion filling
if (disparity_map[index] == 0) {
// Variables to store the nearest non-zero neighbor
int nearest_disparity = -1;
float min_distance = FLT_MAX;
// Iterate over the neighborhood
for (int dy = -max_radius; dy <= max_radius; dy++) {
for (int dx = -max_radius; dx <= max_radius; dx++) {
// Skip the current pixel
if (dx == 0 && dy == 0)
continue;
// Calculate neighbor coordinates
int nx = x + dx;
int ny = y + dy;
// Ensure neighbor is within bounds
if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
// Calculate Manhattan distance
float distance = abs(dx) + abs(dy);
// Check if neighbor has a non-zero disparity
if (disparity_map[ny * width + nx] != 0) {
// Update nearest disparity if closer neighbor found
if (distance < min_distance) {
min_distance = distance;
nearest_disparity = disparity_map[ny * width + nx];
}
}
}
}
}
// Update current pixel with nearest non-zero disparity
occlusion_map[index] = (nearest_disparity != -1) ? nearest_disparity : 0;
}
}
}