Merge pull request #328 from kwagyeman/master

More image filtering stuff
This commit is contained in:
Ibrahim Abd Elkader 2018-04-01 17:46:02 +02:00 committed by GitHub
commit 11a9610902
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 846 additions and 11 deletions

View File

@ -13,6 +13,26 @@ void imlib_binary(image_t *img, list_t *thresholds, bool invert, bool zero)
switch(img->bpp) { switch(img->bpp) {
case IMAGE_BPP_BINARY: { case IMAGE_BPP_BINARY: {
if (!zero) {
for (uint32_t *start = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, 0),
*end = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, img->h);
start < end; start++) {
for (int i = 0; i < UINT32_T_BITS; i++) {
IMAGE_PUT_BINARY_PIXEL_FAST(start, i,
COLOR_THRESHOLD_BINARY(IMAGE_GET_BINARY_PIXEL_FAST(start, i), &lnk_data, invert)
? COLOR_BINARY_MAX : COLOR_BINARY_MIN);
}
}
} else {
for (uint32_t *start = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, 0),
*end = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, img->h);
start < end; start++) {
for (int i = 0; i < UINT32_T_BITS; i++) {
if (COLOR_THRESHOLD_BINARY(IMAGE_GET_BINARY_PIXEL_FAST(start, i), &lnk_data, invert))
IMAGE_PUT_BINARY_PIXEL_FAST(start, i, COLOR_BINARY_MIN);
}
}
}
break; break;
} }
case IMAGE_BPP_GRAYSCALE: { case IMAGE_BPP_GRAYSCALE: {
@ -27,8 +47,8 @@ void imlib_binary(image_t *img, list_t *thresholds, bool invert, bool zero)
for (uint8_t *start = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, 0), for (uint8_t *start = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, 0),
*end = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, img->h); *end = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, img->h);
start < end; start++) { start < end; start++) {
if (COLOR_THRESHOLD_GRAYSCALE(*start, &lnk_data, invert)) *start = if (COLOR_THRESHOLD_GRAYSCALE(*start, &lnk_data, invert))
COLOR_GRAYSCALE_BINARY_MIN; *start = COLOR_GRAYSCALE_BINARY_MIN;
} }
} }
break; break;
@ -45,8 +65,8 @@ void imlib_binary(image_t *img, list_t *thresholds, bool invert, bool zero)
for (uint16_t *start = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, 0), for (uint16_t *start = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, 0),
*end = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, img->h); *end = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, img->h);
start < end; start++) { start < end; start++) {
if (COLOR_THRESHOLD_RGB565(*start, &lnk_data, invert)) *start = if (COLOR_THRESHOLD_RGB565(*start, &lnk_data, invert))
COLOR_RGB565_BINARY_MIN; *start = COLOR_RGB565_BINARY_MIN;
} }
} }
break; break;
@ -711,3 +731,41 @@ void imlib_dilate(image_t *img, int ksize, int threshold, image_t *mask)
// Dilate normally requires one pixel to be 1. // Dilate normally requires one pixel to be 1.
imlib_erode_dilate(img, ksize, threshold, 1, mask); imlib_erode_dilate(img, ksize, threshold, 1, mask);
} }
void imlib_open(image_t *img, int ksize, int threshold, image_t *mask)
{
imlib_erode(img, ksize, (((ksize*2)+1)*((ksize*2)+1))-1 - threshold, mask);
imlib_dilate(img, ksize, 0 + threshold, mask);
}
void imlib_close(image_t *img, int ksize, int threshold, image_t *mask)
{
imlib_dilate(img, ksize, 0 + threshold, mask);
imlib_erode(img, ksize, (((ksize*2)+1)*((ksize*2)+1))-1 - threshold, mask);
}
void imlib_top_hat(image_t *img, int ksize, int threshold, image_t *mask)
{
image_t temp;
temp.w = img->w;
temp.h = img->h;
temp.bpp = img->bpp;
temp.data = fb_alloc(image_size(img));
memcpy(temp.data, img->data, image_size(img));
imlib_open(&temp, ksize, threshold, mask);
imlib_difference(img, NULL, &temp, 0, mask);
fb_free();
}
void imlib_black_hat(image_t *img, int ksize, int threshold, image_t *mask)
{
image_t temp;
temp.w = img->w;
temp.h = img->h;
temp.bpp = img->bpp;
temp.data = fb_alloc(image_size(img));
memcpy(temp.data, img->data, image_size(img));
imlib_close(&temp, ksize, threshold, mask);
imlib_difference(img, NULL, &temp, 0, mask);
fb_free();
}

View File

@ -10,7 +10,28 @@ void imlib_histeq(image_t *img)
{ {
switch(img->bpp) { switch(img->bpp) {
case IMAGE_BPP_BINARY: { case IMAGE_BPP_BINARY: {
// Can't run this on a binary image. int a = img->w * img->h;
float s = (COLOR_BINARY_MAX-COLOR_BINARY_MIN) / ((float) a);
uint32_t *hist = fb_alloc0((COLOR_BINARY_MAX-COLOR_BINARY_MIN+1)*sizeof(uint32_t));
uint32_t *pixels = (uint32_t *) img->data;
// Compute the image histogram
for (int i=0; i<a; i++) {
hist[pixels[i]-COLOR_BINARY_MIN] += 1;
}
// Compute the CDF
for (int i=0, sum=0; i<(COLOR_BINARY_MAX-COLOR_BINARY_MIN+1); i++) {
sum += hist[i];
hist[i] = sum;
}
for (int i=0; i<a; i++) {
int pixel = pixels[i];
pixels[i] = (s * hist[pixel-COLOR_BINARY_MIN]) + COLOR_BINARY_MIN;
}
fb_free();
break; break;
} }
case IMAGE_BPP_GRAYSCALE: { case IMAGE_BPP_GRAYSCALE: {
@ -88,7 +109,58 @@ void imlib_mean_filter(image_t *img, const int ksize, bool threshold, int offset
switch(img->bpp) { switch(img->bpp) {
case IMAGE_BPP_BINARY: { case IMAGE_BPP_BINARY: {
// Can't run this on a binary image. buf.data = fb_alloc(IMAGE_BINARY_LINE_LEN_BYTES(img) * brows);
for (int y = 0, yy = img->h; y < yy; y++) {
uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y);
uint32_t *buf_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, (y % brows));
for (int x = 0, xx = img->w; x < xx; x++) {
if (mask && (!image_get_mask_pixel(mask, x, y))) {
IMAGE_PUT_BINARY_PIXEL_FAST(buf_row_ptr, x, IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x));
continue; // Short circuit.
}
int acc = 0;
for (int j = -ksize; j <= ksize; j++) {
uint32_t *k_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img,
IM_MIN(IM_MAX(y + j, 0), (img->h - 1)));
for (int k = -ksize; k <= ksize; k++) {
acc += IMAGE_GET_BINARY_PIXEL_FAST(k_row_ptr,
IM_MIN(IM_MAX(x + k, 0), (img->w - 1)));
}
}
int pixel = fast_roundf(acc * over_n);
if (threshold) {
if (((pixel - offset) < IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x)) ^ invert) {
pixel = COLOR_BINARY_MAX;
} else {
pixel = COLOR_BINARY_MIN;
}
}
IMAGE_PUT_BINARY_PIXEL_FAST(buf_row_ptr, x, pixel);
}
if (y >= ksize) { // Transfer buffer lines...
memcpy(IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, (y - ksize)),
IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, ((y - ksize) % brows)),
IMAGE_BINARY_LINE_LEN_BYTES(img));
}
}
// Copy any remaining lines from the buffer image...
for (int y = img->h - ksize, yy = img->h; y < yy; y++) {
memcpy(IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y),
IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, (y % brows)),
IMAGE_BINARY_LINE_LEN_BYTES(img));
}
fb_free();
break; break;
} }
case IMAGE_BPP_GRAYSCALE: { case IMAGE_BPP_GRAYSCALE: {
@ -224,7 +296,62 @@ void imlib_median_filter(image_t *img, const int ksize, float percentile, bool t
switch(img->bpp) { switch(img->bpp) {
case IMAGE_BPP_BINARY: { case IMAGE_BPP_BINARY: {
// Can't run this on a binary image. buf.data = fb_alloc(IMAGE_BINARY_LINE_LEN_BYTES(img) * brows);
int *data = fb_alloc(n*sizeof(int));
for (int y = 0, yy = img->h; y < yy; y++) {
uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y);
uint32_t *buf_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, (y % brows));
for (int x = 0, xx = img->w; x < xx; x++) {
if (mask && (!image_get_mask_pixel(mask, x, y))) {
IMAGE_PUT_BINARY_PIXEL_FAST(buf_row_ptr, x, IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x));
continue; // Short circuit.
}
int *data_ptr = data;
for (int j = -ksize; j <= ksize; j++) {
uint32_t *k_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img,
IM_MIN(IM_MAX(y + j, 0), (img->h - 1)));
for (int k = -ksize; k <= ksize; k++) {
*data_ptr++ = IMAGE_GET_BINARY_PIXEL_FAST(k_row_ptr,
IM_MIN(IM_MAX(x + k, 0), (img->w - 1)));
}
}
fsort(data, n);
int pixel = data[int_percentile];
if (threshold) {
if (((pixel - offset) < IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x)) ^ invert) {
pixel = COLOR_BINARY_MAX;
} else {
pixel = COLOR_BINARY_MIN;
}
}
IMAGE_PUT_BINARY_PIXEL_FAST(buf_row_ptr, x, pixel);
}
if (y >= ksize) { // Transfer buffer lines...
memcpy(IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, (y - ksize)),
IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, ((y - ksize) % brows)),
IMAGE_BINARY_LINE_LEN_BYTES(img));
}
}
// Copy any remaining lines from the buffer image...
for (int y = img->h - ksize, yy = img->h; y < yy; y++) {
memcpy(IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y),
IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, (y % brows)),
IMAGE_BINARY_LINE_LEN_BYTES(img));
}
fb_free();
fb_free();
break; break;
} }
case IMAGE_BPP_GRAYSCALE: { case IMAGE_BPP_GRAYSCALE: {
@ -372,7 +499,68 @@ void imlib_mode_filter(image_t *img, const int ksize, bool threshold, int offset
switch(img->bpp) { switch(img->bpp) {
case IMAGE_BPP_BINARY: { case IMAGE_BPP_BINARY: {
// Can't run this on a binary image. buf.data = fb_alloc(IMAGE_BINARY_LINE_LEN_BYTES(img) * brows);
int *bins = fb_alloc((COLOR_BINARY_MAX-COLOR_BINARY_MIN+1)*sizeof(int));
for (int y = 0, yy = img->h; y < yy; y++) {
uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y);
uint32_t *buf_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, (y % brows));
for (int x = 0, xx = img->w; x < xx; x++) {
if (mask && (!image_get_mask_pixel(mask, x, y))) {
IMAGE_PUT_BINARY_PIXEL_FAST(buf_row_ptr, x, IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x));
continue; // Short circuit.
}
memset(bins, 0, (COLOR_BINARY_MAX-COLOR_BINARY_MIN+1)*sizeof(int));
int mcount = 0, mode = 0;
for (int j = -ksize; j <= ksize; j++) {
uint32_t *k_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img,
IM_MIN(IM_MAX(y + j, 0), (img->h - 1)));
for (int k = -ksize; k <= ksize; k++) {
int pixel = IMAGE_GET_BINARY_PIXEL_FAST(k_row_ptr,
IM_MIN(IM_MAX(x + k, 0), (img->w - 1)));
bins[pixel]++;
if (bins[pixel] > mcount) {
mcount = bins[pixel];
mode = pixel;
}
}
}
int pixel = mode;
if (threshold) {
if (((pixel - offset) < IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x)) ^ invert) {
pixel = COLOR_BINARY_MAX;
} else {
pixel = COLOR_BINARY_MIN;
}
}
IMAGE_PUT_BINARY_PIXEL_FAST(buf_row_ptr, x, pixel);
}
if (y >= ksize) { // Transfer buffer lines...
memcpy(IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, (y - ksize)),
IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, ((y - ksize) % brows)),
IMAGE_BINARY_LINE_LEN_BYTES(img));
}
}
// Copy any remaining lines from the buffer image...
for (int y = img->h - ksize, yy = img->h; y < yy; y++) {
memcpy(IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y),
IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, (y % brows)),
IMAGE_BINARY_LINE_LEN_BYTES(img));
}
fb_free();
fb_free();
break; break;
} }
case IMAGE_BPP_GRAYSCALE: { case IMAGE_BPP_GRAYSCALE: {
@ -546,7 +734,60 @@ void imlib_midpoint_filter(image_t *img, const int ksize, float bias, bool thres
switch(img->bpp) { switch(img->bpp) {
case IMAGE_BPP_BINARY: { case IMAGE_BPP_BINARY: {
// Can't run this on a binary image. buf.data = fb_alloc(IMAGE_BINARY_LINE_LEN_BYTES(img) * brows);
for (int y = 0, yy = img->h; y < yy; y++) {
uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y);
uint32_t *buf_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, (y % brows));
for (int x = 0, xx = img->w; x < xx; x++) {
if (mask && (!image_get_mask_pixel(mask, x, y))) {
IMAGE_PUT_BINARY_PIXEL_FAST(buf_row_ptr, x, IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x));
continue; // Short circuit.
}
int min = COLOR_BINARY_MAX, max = COLOR_BINARY_MIN;
for (int j = -ksize; j <= ksize; j++) {
uint32_t *k_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img,
IM_MIN(IM_MAX(y + j, 0), (img->h - 1)));
for (int k = -ksize; k <= ksize; k++) {
int pixel = IMAGE_GET_BINARY_PIXEL_FAST(k_row_ptr,
IM_MIN(IM_MAX(x + k, 0), (img->w - 1)));
min = IM_MIN(min, pixel);
max = IM_MAX(max, pixel);
}
}
int pixel = fast_roundf((min*min_bias)+(max*max_bias));
if (threshold) {
if (((pixel - offset) < IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x)) ^ invert) {
pixel = COLOR_BINARY_MAX;
} else {
pixel = COLOR_BINARY_MIN;
}
}
IMAGE_PUT_BINARY_PIXEL_FAST(buf_row_ptr, x, pixel);
}
if (y >= ksize) { // Transfer buffer lines...
memcpy(IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, (y - ksize)),
IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, ((y - ksize) % brows)),
IMAGE_BINARY_LINE_LEN_BYTES(img));
}
}
// Copy any remaining lines from the buffer image...
for (int y = img->h - ksize, yy = img->h; y < yy; y++) {
memcpy(IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y),
IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, (y % brows)),
IMAGE_BINARY_LINE_LEN_BYTES(img));
}
fb_free();
break; break;
} }
case IMAGE_BPP_GRAYSCALE: { case IMAGE_BPP_GRAYSCALE: {
@ -692,7 +933,58 @@ void imlib_morph(image_t *img, const int ksize, const int *krn, const float m, c
switch(img->bpp) { switch(img->bpp) {
case IMAGE_BPP_BINARY: { case IMAGE_BPP_BINARY: {
// Can't run this on a binary image. buf.data = fb_alloc(IMAGE_BINARY_LINE_LEN_BYTES(img) * brows);
for (int y = 0, yy = img->h; y < yy; y++) {
uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y);
uint32_t *buf_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, (y % brows));
for (int x = 0, xx = img->w; x < xx; x++) {
if (mask && (!image_get_mask_pixel(mask, x, y))) {
IMAGE_PUT_BINARY_PIXEL_FAST(buf_row_ptr, x, IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x));
continue; // Short circuit.
}
int acc = 0, ptr = 0;
for (int j = -ksize; j <= ksize; j++) {
uint32_t *k_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img,
IM_MIN(IM_MAX(y + j, 0), (img->h - 1)));
for (int k = -ksize; k <= ksize; k++) {
acc += krn[ptr++] * IMAGE_GET_BINARY_PIXEL_FAST(k_row_ptr,
IM_MIN(IM_MAX(x + k, 0), (img->w - 1)));
}
}
int pixel = IM_MAX(IM_MIN(fast_roundf(acc * m) + b, COLOR_BINARY_MAX), COLOR_BINARY_MIN);
if (threshold) {
if (((pixel - offset) < IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x)) ^ invert) {
pixel = COLOR_BINARY_MAX;
} else {
pixel = COLOR_BINARY_MIN;
}
}
IMAGE_PUT_BINARY_PIXEL_FAST(buf_row_ptr, x, pixel);
}
if (y >= ksize) { // Transfer buffer lines...
memcpy(IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, (y - ksize)),
IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, ((y - ksize) % brows)),
IMAGE_BINARY_LINE_LEN_BYTES(img));
}
}
// Copy any remaining lines from the buffer image...
for (int y = img->h - ksize, yy = img->h; y < yy; y++) {
memcpy(IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y),
IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, (y % brows)),
IMAGE_BINARY_LINE_LEN_BYTES(img));
}
fb_free();
break; break;
} }
case IMAGE_BPP_GRAYSCALE: { case IMAGE_BPP_GRAYSCALE: {
@ -815,3 +1107,285 @@ void imlib_morph(image_t *img, const int ksize, const int *krn, const float m, c
} }
} }
} }
static float gaussian(int x, float sigma)
{
return fast_expf((x * x) / (-2.0f * sigma * sigma)) / (sigma * 2.506628f); // sqrt(2 * PI)
}
static float distance(int x, int y)
{
return fast_sqrtf((x * x) + (y * y));
}
void imlib_bilateral_filter(image_t *img, const int ksize, float color_sigma, float space_sigma, bool threshold, int offset, bool invert, image_t *mask)
{
int brows = ksize + 1;
image_t buf;
buf.w = img->w;
buf.h = brows;
buf.bpp = img->bpp;
switch(img->bpp) {
case IMAGE_BPP_BINARY: {
buf.data = fb_alloc(IMAGE_BINARY_LINE_LEN_BYTES(img) * brows);
float *gi_lut = fb_alloc((COLOR_BINARY_MAX - COLOR_BINARY_MIN + 1) * sizeof(float));
for (int i = COLOR_BINARY_MIN; i <= COLOR_BINARY_MAX; i++) {
gi_lut[i] = gaussian(i, color_sigma);
}
int n = (ksize * 2) + 1;
float *gs_lut = fb_alloc(n * n * sizeof(float));
for (int y = -ksize; y <= ksize; y++) {
for (int x = -ksize; x <= ksize; x++) {
gs_lut[(n * (y + ksize)) + (x + ksize)] = gaussian(distance(x, y), space_sigma);
}
}
for (int y = 0, yy = img->h; y < yy; y++) {
uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y);
uint32_t *buf_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, (y % brows));
for (int x = 0, xx = img->w; x < xx; x++) {
if (mask && (!image_get_mask_pixel(mask, x, y))) {
IMAGE_PUT_BINARY_PIXEL_FAST(buf_row_ptr, x, IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x));
continue; // Short circuit.
}
int this_pixel = IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x);
float i_acc = 0, w_acc = 0;
for (int j = -ksize; j <= ksize; j++) {
uint32_t *k_row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img,
IM_MIN(IM_MAX(y + j, 0), (img->h - 1)));
for (int k = -ksize; k <= ksize; k++) {
int pixel = IMAGE_GET_BINARY_PIXEL_FAST(k_row_ptr,
IM_MIN(IM_MAX(x + k, 0), (img->w - 1)));
float w = gi_lut[abs(this_pixel - pixel)] * gs_lut[(n * (j + ksize)) + (k + ksize)];
i_acc += pixel * w;
w_acc += w;
}
}
int pixel = fast_roundf(IM_MIN(IM_DIV(i_acc, w_acc), COLOR_BINARY_MAX));
if (threshold) {
if (((pixel - offset) < IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x)) ^ invert) {
pixel = COLOR_BINARY_MAX;
} else {
pixel = COLOR_BINARY_MIN;
}
}
IMAGE_PUT_BINARY_PIXEL_FAST(buf_row_ptr, x, pixel);
}
if (y >= ksize) { // Transfer buffer lines...
memcpy(IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, (y - ksize)),
IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, ((y - ksize) % brows)),
IMAGE_BINARY_LINE_LEN_BYTES(img));
}
}
// Copy any remaining lines from the buffer image...
for (int y = img->h - ksize, yy = img->h; y < yy; y++) {
memcpy(IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, y),
IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(&buf, (y % brows)),
IMAGE_BINARY_LINE_LEN_BYTES(img));
}
fb_free();
fb_free();
fb_free();
break;
}
case IMAGE_BPP_GRAYSCALE: {
buf.data = fb_alloc(IMAGE_GRAYSCALE_LINE_LEN_BYTES(img) * brows);
float *gi_lut = fb_alloc((COLOR_GRAYSCALE_MAX - COLOR_GRAYSCALE_MIN + 1) * sizeof(float));
for (int i = COLOR_GRAYSCALE_MIN; i <= COLOR_GRAYSCALE_MAX; i++) {
gi_lut[i] = gaussian(i, color_sigma);
}
int n = (ksize * 2) + 1;
float *gs_lut = fb_alloc(n * n * sizeof(float));
for (int y = -ksize; y <= ksize; y++) {
for (int x = -ksize; x <= ksize; x++) {
gs_lut[(n * (y + ksize)) + (x + ksize)] = gaussian(distance(x, y), space_sigma);
}
}
for (int y = 0, yy = img->h; y < yy; y++) {
uint8_t *row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y);
uint8_t *buf_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(&buf, (y % brows));
for (int x = 0, xx = img->w; x < xx; x++) {
if (mask && (!image_get_mask_pixel(mask, x, y))) {
IMAGE_PUT_GRAYSCALE_PIXEL_FAST(buf_row_ptr, x, IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x));
continue; // Short circuit.
}
int this_pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x);
float i_acc = 0, w_acc = 0;
for (int j = -ksize; j <= ksize; j++) {
uint8_t *k_row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img,
IM_MIN(IM_MAX(y + j, 0), (img->h - 1)));
for (int k = -ksize; k <= ksize; k++) {
int pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(k_row_ptr,
IM_MIN(IM_MAX(x + k, 0), (img->w - 1)));
float w = gi_lut[abs(this_pixel - pixel)] * gs_lut[(n * (j + ksize)) + (k + ksize)];
i_acc += pixel * w;
w_acc += w;
}
}
int pixel = fast_roundf(IM_MIN(IM_DIV(i_acc, w_acc), COLOR_GRAYSCALE_MAX));
if (threshold) {
if (((pixel - offset) < IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x)) ^ invert) {
pixel = COLOR_GRAYSCALE_BINARY_MAX;
} else {
pixel = COLOR_GRAYSCALE_BINARY_MIN;
}
}
IMAGE_PUT_GRAYSCALE_PIXEL_FAST(buf_row_ptr, x, pixel);
}
if (y >= ksize) { // Transfer buffer lines...
memcpy(IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, (y - ksize)),
IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(&buf, ((y - ksize) % brows)),
IMAGE_GRAYSCALE_LINE_LEN_BYTES(img));
}
}
// Copy any remaining lines from the buffer image...
for (int y = img->h - ksize, yy = img->h; y < yy; y++) {
memcpy(IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, y),
IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(&buf, (y % brows)),
IMAGE_GRAYSCALE_LINE_LEN_BYTES(img));
}
fb_free();
fb_free();
fb_free();
break;
}
case IMAGE_BPP_RGB565: {
buf.data = fb_alloc(IMAGE_RGB565_LINE_LEN_BYTES(img) * brows);
float *r_gi_lut = fb_alloc((COLOR_R5_MAX - COLOR_R5_MIN + 1) * sizeof(float));
float *g_gi_lut = fb_alloc((COLOR_G6_MAX - COLOR_G6_MIN + 1) * sizeof(float));
float *b_gi_lut = fb_alloc((COLOR_B5_MAX - COLOR_B5_MIN + 1) * sizeof(float));
for (int i = COLOR_R5_MIN; i <= COLOR_R5_MAX; i++) {
r_gi_lut[i] = gaussian(i, color_sigma);
}
for (int i = COLOR_G6_MIN; i <= COLOR_G6_MAX; i++) {
g_gi_lut[i] = gaussian(i, color_sigma);
}
for (int i = COLOR_B5_MIN; i <= COLOR_B5_MAX; i++) {
b_gi_lut[i] = gaussian(i, color_sigma);
}
int n = (ksize * 2) + 1;
float *gs_lut = fb_alloc(n * n * sizeof(float));
for (int y = -ksize; y <= ksize; y++) {
for (int x = -ksize; x <= ksize; x++) {
gs_lut[(n * (y + ksize)) + (x + ksize)] = gaussian(distance(x, y), space_sigma);
}
}
for (int y = 0, yy = img->h; y < yy; y++) {
uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y);
uint16_t *buf_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&buf, (y % brows));
for (int x = 0, xx = img->w; x < xx; x++) {
if (mask && (!image_get_mask_pixel(mask, x, y))) {
IMAGE_PUT_RGB565_PIXEL_FAST(buf_row_ptr, x, IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x));
continue; // Short circuit.
}
int this_pixel = IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x);
int r_this_pixel = COLOR_RGB565_TO_R5(this_pixel);
int g_this_pixel = COLOR_RGB565_TO_G6(this_pixel);
int b_this_pixel = COLOR_RGB565_TO_B5(this_pixel);
float r_i_acc = 0, r_w_acc = 0;
float g_i_acc = 0, g_w_acc = 0;
float b_i_acc = 0, b_w_acc = 0;
for (int j = -ksize; j <= ksize; j++) {
uint16_t *k_row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img,
IM_MIN(IM_MAX(y + j, 0), (img->h - 1)));
for (int k = -ksize; k <= ksize; k++) {
int pixel = IMAGE_GET_RGB565_PIXEL_FAST(k_row_ptr,
IM_MIN(IM_MAX(x + k, 0), (img->w - 1)));
int r_pixel = COLOR_RGB565_TO_R5(pixel);
int g_pixel = COLOR_RGB565_TO_G6(pixel);
int b_pixel = COLOR_RGB565_TO_B5(pixel);
float gs = gs_lut[(n * (j + ksize)) + (k + ksize)];
float r_w = r_gi_lut[abs(r_this_pixel - r_pixel)] * gs;
float g_w = g_gi_lut[abs(g_this_pixel - g_pixel)] * gs;
float b_w = b_gi_lut[abs(b_this_pixel - b_pixel)] * gs;
r_i_acc += r_pixel * r_w;
r_w_acc += r_w;
g_i_acc += g_pixel * g_w;
g_w_acc += g_w;
b_i_acc += b_pixel * b_w;
b_w_acc += b_w;
}
}
int pixel = COLOR_R5_G6_B5_TO_RGB565(fast_roundf(IM_MIN(IM_DIV(r_i_acc, r_w_acc), COLOR_R5_MAX)),
fast_roundf(IM_MIN(IM_DIV(g_i_acc, g_w_acc), COLOR_G6_MAX)),
fast_roundf(IM_MIN(IM_DIV(b_i_acc, b_w_acc), COLOR_B5_MAX)));
if (threshold) {
if (((COLOR_RGB565_TO_Y(pixel) - offset) < COLOR_RGB565_TO_Y(IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x))) ^ invert) {
pixel = COLOR_RGB565_BINARY_MAX;
} else {
pixel = COLOR_RGB565_BINARY_MIN;
}
}
IMAGE_PUT_RGB565_PIXEL_FAST(buf_row_ptr, x, pixel);
}
if (y >= ksize) { // Transfer buffer lines...
memcpy(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, (y - ksize)),
IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&buf, ((y - ksize) % brows)),
IMAGE_RGB565_LINE_LEN_BYTES(img));
}
}
// Copy any remaining lines from the buffer image...
for (int y = img->h - ksize, yy = img->h; y < yy; y++) {
memcpy(IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, y),
IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(&buf, (y % brows)),
IMAGE_RGB565_LINE_LEN_BYTES(img));
}
fb_free();
fb_free();
fb_free();
fb_free();
fb_free();
break;
}
default: {
break;
}
}
}

View File

@ -127,7 +127,13 @@ typedef struct color_thresholds_list_lnk_data
} }
color_thresholds_list_lnk_data_t; color_thresholds_list_lnk_data_t;
#define COLOR_THRESHOLD_BINARY(pixel, threshold, invert) ((pixel) ^ (invert)) #define COLOR_THRESHOLD_BINARY(pixel, threshold, invert) \
({ \
__typeof__ (pixel) _pixel = (pixel); \
__typeof__ (threshold) _threshold = (threshold); \
__typeof__ (invert) _invert = (invert); \
((_threshold->LMin <= _pixel) && (_pixel <= _threshold->LMax)) ^ _invert; \
})
#define COLOR_THRESHOLD_GRAYSCALE(pixel, threshold, invert) \ #define COLOR_THRESHOLD_GRAYSCALE(pixel, threshold, invert) \
({ \ ({ \
@ -1222,6 +1228,10 @@ void imlib_b_xor(image_t *img, const char *path, image_t *other, int scalar, ima
void imlib_b_xnor(image_t *img, const char *path, image_t *other, int scalar, image_t *mask); void imlib_b_xnor(image_t *img, const char *path, image_t *other, int scalar, image_t *mask);
void imlib_erode(image_t *img, int ksize, int threshold, image_t *mask); void imlib_erode(image_t *img, int ksize, int threshold, image_t *mask);
void imlib_dilate(image_t *img, int ksize, int threshold, image_t *mask); void imlib_dilate(image_t *img, int ksize, int threshold, image_t *mask);
void imlib_open(image_t *img, int ksize, int threshold, image_t *mask);
void imlib_close(image_t *img, int ksize, int threshold, image_t *mask);
void imlib_top_hat(image_t *img, int ksize, int threshold, image_t *mask);
void imlib_black_hat(image_t *img, int ksize, int threshold, image_t *mask);
// Math Functions // Math Functions
void imlib_negate(image_t *img); void imlib_negate(image_t *img);
void imlib_replace(image_t *img, const char *path, image_t *other, int scalar, bool hmirror, bool vflip); void imlib_replace(image_t *img, const char *path, image_t *other, int scalar, bool hmirror, bool vflip);
@ -1240,6 +1250,7 @@ void imlib_median_filter(image_t *img, const int ksize, float percentile, bool t
void imlib_mode_filter(image_t *img, const int ksize, bool threshold, int offset, bool invert, image_t *mask); void imlib_mode_filter(image_t *img, const int ksize, bool threshold, int offset, bool invert, image_t *mask);
void imlib_midpoint_filter(image_t *img, const int ksize, float bias, bool threshold, int offset, bool invert, image_t *mask); void imlib_midpoint_filter(image_t *img, const int ksize, float bias, bool threshold, int offset, bool invert, image_t *mask);
void imlib_morph(image_t *img, const int ksize, const int *krn, const float m, const int b, bool threshold, int offset, bool invert, image_t *mask); void imlib_morph(image_t *img, const int ksize, const int *krn, const float m, const int b, bool threshold, int offset, bool invert, image_t *mask);
void imlib_bilateral_filter(image_t *img, const int ksize, float color_sigma, float space_sigma, bool threshold, int offset, bool invert, image_t *mask);
// Image Correction // Image Correction
void imlib_logpolar_int(image_t *dst, image_t *src, rectangle_t *roi, bool linear, bool reverse); // helper/internal void imlib_logpolar_int(image_t *dst, image_t *src, rectangle_t *roi, bool linear, bool reverse); // helper/internal
void imlib_logpolar(image_t *img, bool linear, bool reverse); void imlib_logpolar(image_t *img, bool linear, bool reverse);

View File

@ -1401,6 +1401,70 @@ STATIC mp_obj_t py_image_dilate(uint n_args, const mp_obj_t *args, mp_map_t *kw_
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_dilate_obj, 2, py_image_dilate); STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_dilate_obj, 2, py_image_dilate);
STATIC mp_obj_t py_image_open(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
int arg_ksize =
py_helper_arg_to_ksize(args[1]);
int arg_threshold =
py_helper_keyword_int(n_args, args, 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_threshold), 0);
image_t *arg_msk =
py_helper_keyword_to_image_mutable_mask(n_args, args, 3, kw_args);
fb_alloc_mark();
imlib_open(py_helper_arg_to_image_mutable(args[0]), arg_ksize, arg_threshold, arg_msk);
fb_alloc_free_till_mark();
return args[0];
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_open_obj, 2, py_image_open);
STATIC mp_obj_t py_image_close(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
int arg_ksize =
py_helper_arg_to_ksize(args[1]);
int arg_threshold =
py_helper_keyword_int(n_args, args, 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_threshold), 0);
image_t *arg_msk =
py_helper_keyword_to_image_mutable_mask(n_args, args, 3, kw_args);
fb_alloc_mark();
imlib_close(py_helper_arg_to_image_mutable(args[0]), arg_ksize, arg_threshold, arg_msk);
fb_alloc_free_till_mark();
return args[0];
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_close_obj, 2, py_image_close);
STATIC mp_obj_t py_image_top_hat(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
int arg_ksize =
py_helper_arg_to_ksize(args[1]);
int arg_threshold =
py_helper_keyword_int(n_args, args, 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_threshold), 0);
image_t *arg_msk =
py_helper_keyword_to_image_mutable_mask(n_args, args, 3, kw_args);
fb_alloc_mark();
imlib_top_hat(py_helper_arg_to_image_mutable(args[0]), arg_ksize, arg_threshold, arg_msk);
fb_alloc_free_till_mark();
return args[0];
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_top_hat_obj, 2, py_image_top_hat);
STATIC mp_obj_t py_image_black_hat(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
int arg_ksize =
py_helper_arg_to_ksize(args[1]);
int arg_threshold =
py_helper_keyword_int(n_args, args, 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_threshold), 0);
image_t *arg_msk =
py_helper_keyword_to_image_mutable_mask(n_args, args, 3, kw_args);
fb_alloc_mark();
imlib_black_hat(py_helper_arg_to_image_mutable(args[0]), arg_ksize, arg_threshold, arg_msk);
fb_alloc_free_till_mark();
return args[0];
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_black_hat_obj, 2, py_image_black_hat);
/////////////// ///////////////
// Math Methods // Math Methods
/////////////// ///////////////
@ -1917,6 +1981,34 @@ STATIC mp_obj_t py_image_laplacian(uint n_args, const mp_obj_t *args, mp_map_t *
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_laplacian_obj, 2, py_image_laplacian); STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_laplacian_obj, 2, py_image_laplacian);
STATIC mp_obj_t py_image_bilateral(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
image_t *arg_img =
py_helper_arg_to_image_mutable(args[0]);
int arg_ksize =
py_helper_arg_to_ksize(args[1]);
float arg_color_sigma =
py_helper_keyword_float(n_args, args, 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_color_sigma), 6);
PY_ASSERT_TRUE_MSG((0 <= arg_color_sigma), "Error: 0 <= color_sigma!");
float arg_space_sigma =
py_helper_keyword_float(n_args, args, 3, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_space_sigma), 6);
PY_ASSERT_TRUE_MSG((0 <= arg_space_sigma), "Error: 0 <= space_sigma!");
bool arg_threshold =
py_helper_keyword_int(n_args, args, 4, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_threshold), false);
int arg_offset =
py_helper_keyword_int(n_args, args, 5, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_offset), 0);
bool arg_invert =
py_helper_keyword_int(n_args, args, 6, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_invert), false);
image_t *arg_msk =
py_helper_keyword_to_image_mutable_mask(n_args, args, 7, kw_args);
fb_alloc_mark();
imlib_bilateral_filter(arg_img, arg_ksize, arg_color_sigma, arg_space_sigma, arg_threshold, arg_offset, arg_invert, arg_msk);
fb_alloc_free_till_mark();
return args[0];
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_bilateral_obj, 2, py_image_bilateral);
///////////////////////// /////////////////////////
// Shadow Removal Methods // Shadow Removal Methods
///////////////////////// /////////////////////////
@ -4819,6 +4911,10 @@ static const mp_rom_map_elem_t locals_dict_table[] = {
{MP_ROM_QSTR(MP_QSTR_b_xnor), MP_ROM_PTR(&py_image_b_xnor_obj)}, {MP_ROM_QSTR(MP_QSTR_b_xnor), MP_ROM_PTR(&py_image_b_xnor_obj)},
{MP_ROM_QSTR(MP_QSTR_erode), MP_ROM_PTR(&py_image_erode_obj)}, {MP_ROM_QSTR(MP_QSTR_erode), MP_ROM_PTR(&py_image_erode_obj)},
{MP_ROM_QSTR(MP_QSTR_dilate), MP_ROM_PTR(&py_image_dilate_obj)}, {MP_ROM_QSTR(MP_QSTR_dilate), MP_ROM_PTR(&py_image_dilate_obj)},
{MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&py_image_open_obj)},
{MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&py_image_close_obj)},
{MP_ROM_QSTR(MP_QSTR_top_hat), MP_ROM_PTR(&py_image_top_hat_obj)},
{MP_ROM_QSTR(MP_QSTR_black_hat), MP_ROM_PTR(&py_image_black_hat_obj)},
/* Math Methods */ /* Math Methods */
{MP_ROM_QSTR(MP_QSTR_negate), MP_ROM_PTR(&py_image_negate_obj)}, {MP_ROM_QSTR(MP_QSTR_negate), MP_ROM_PTR(&py_image_negate_obj)},
{MP_ROM_QSTR(MP_QSTR_replace), MP_ROM_PTR(&py_image_replace_obj)}, {MP_ROM_QSTR(MP_QSTR_replace), MP_ROM_PTR(&py_image_replace_obj)},
@ -4841,6 +4937,7 @@ static const mp_rom_map_elem_t locals_dict_table[] = {
{MP_ROM_QSTR(MP_QSTR_gaussian), MP_ROM_PTR(&py_image_gaussian_obj)}, {MP_ROM_QSTR(MP_QSTR_gaussian), MP_ROM_PTR(&py_image_gaussian_obj)},
{MP_ROM_QSTR(MP_QSTR_gaussian_blur), MP_ROM_PTR(&py_image_gaussian_obj)}, {MP_ROM_QSTR(MP_QSTR_gaussian_blur), MP_ROM_PTR(&py_image_gaussian_obj)},
{MP_ROM_QSTR(MP_QSTR_laplacian), MP_ROM_PTR(&py_image_laplacian_obj)}, {MP_ROM_QSTR(MP_QSTR_laplacian), MP_ROM_PTR(&py_image_laplacian_obj)},
{MP_ROM_QSTR(MP_QSTR_bilateral), MP_ROM_PTR(&py_image_bilateral_obj)},
/* Shadow Removal Methods */ /* Shadow Removal Methods */
#ifdef IMLIB_ENABLE_REMOVE_SHADOWS #ifdef IMLIB_ENABLE_REMOVE_SHADOWS
{MP_ROM_QSTR(MP_QSTR_remove_shadows), MP_ROM_PTR(&py_image_remove_shadows_obj)}, {MP_ROM_QSTR(MP_QSTR_remove_shadows), MP_ROM_PTR(&py_image_remove_shadows_obj)},

View File

@ -408,6 +408,26 @@ Q(dilate)
// duplicate Q(threshold) // duplicate Q(threshold)
// duplicate Q(mask) // duplicate Q(mask)
// Open
// duplicate Q(open)
// duplicate Q(threshold)
// duplicate Q(mask)
// Close
// duplicate Q(close)
// duplicate Q(threshold)
// duplicate Q(mask)
// Top Hat
Q(top_hat)
// duplicate Q(threshold)
// duplicate Q(mask)
// Black Hat
Q(black_hat)
// duplicate Q(threshold)
// duplicate Q(mask)
// Negate // Negate
Q(negate) Q(negate)
@ -516,6 +536,15 @@ Q(sharpen)
// duplicate Q(invert) // duplicate Q(invert)
// duplicate Q(mask) // duplicate Q(mask)
// Bilateral
Q(bilateral)
Q(color_sigma)
Q(space_sigma)
// duplicate Q(threshold)
// duplicate Q(offset)
// duplicate Q(invert)
// duplicate Q(mask)
// Shadow Removal // Shadow Removal
Q(remove_shadows) Q(remove_shadows)

View File

@ -0,0 +1,33 @@
# Color Bilteral Filter Example
#
# This example shows off using the bilateral filter on color images.
import sensor, image, time
sensor.reset() # Initialize the camera sensor.
sensor.set_pixformat(sensor.RGB565) # or sensor.RGB565
sensor.set_framesize(sensor.QQVGA) # or sensor.QVGA (or others)
sensor.skip_frames(time = 2000) # Let new settings take affect.
clock = time.clock() # Tracks FPS.
while(True):
clock.tick() # Track elapsed milliseconds between snapshots().
img = sensor.snapshot() # Take a picture and return the image.
# color_sigma controls how close color wise pixels have to be to each other to be
# blured togheter. A smaller value means they have to be closer.
# A larger value is less strict.
# space_sigma controls how close space wise pixels have to be to each other to be
# blured togheter. A smaller value means they have to be closer.
# A larger value is less strict.
# Run the kernel on every pixel of the image.
img.bilateral(3, color_sigma=5, space_sigma=5)
# Note that the bilateral filter can introduce image defects if you set
# color_sigma/space_sigma to aggresively. Increase the sigma values until
# the defects go away if you see them.
print(clock.fps()) # Note: Your OpenMV Cam runs about half as fast while
# connected to your computer. The FPS should increase once disconnected.

View File

@ -0,0 +1,33 @@
# Grayscale Bilteral Filter Example
#
# This example shows off using the bilateral filter on grayscale images.
import sensor, image, time
sensor.reset() # Initialize the camera sensor.
sensor.set_pixformat(sensor.GRAYSCALE) # or sensor.RGB565
sensor.set_framesize(sensor.QQVGA) # or sensor.QVGA (or others)
sensor.skip_frames(time = 2000) # Let new settings take affect.
clock = time.clock() # Tracks FPS.
while(True):
clock.tick() # Track elapsed milliseconds between snapshots().
img = sensor.snapshot() # Take a picture and return the image.
# color_sigma controls how close color wise pixels have to be to each other to be
# blured togheter. A smaller value means they have to be closer.
# A larger value is less strict.
# space_sigma controls how close space wise pixels have to be to each other to be
# blured togheter. A smaller value means they have to be closer.
# A larger value is less strict.
# Run the kernel on every pixel of the image.
img.bilateral(3, color_sigma=20, space_sigma=20)
# Note that the bilateral filter can introduce image defects if you set
# color_sigma/space_sigma to aggresively. Increase the sigma values until
# the defects go away if you see them.
print(clock.fps()) # Note: Your OpenMV Cam runs about half as fast while
# connected to your computer. The FPS should increase once disconnected.