Merge pull request #285 from kwagyeman/compare_methods

Compare methods
This commit is contained in:
Ibrahim Abd Elkader 2017-12-23 22:22:22 +02:00 committed by GitHub
commit 7346efbf0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 325 additions and 32 deletions

View File

@ -397,7 +397,7 @@ static void imlib_read_pixels(FIL *fp, image_t *img, int line_start, int line_en
}
}
void imlib_image_operation(image_t *img, const char *path, image_t *other, line_op_t op)
void imlib_image_operation(image_t *img, const char *path, image_t *other, line_op_t op, void *data)
{
if (path) {
uint32_t size = fb_avail() / 2;
@ -429,9 +429,9 @@ void imlib_image_operation(image_t *img, const char *path, image_t *other, line_
imlib_read_pixels(&fp, &temp, 0, can_do, &rs);
for (int j=0; j<can_do; j++) {
if (!vflipped) {
op(img, i+j, temp.pixels+(temp.w*temp.bpp*j));
op(img, i+j, temp.pixels+(temp.w*temp.bpp*j), data);
} else {
op(img, (img->h-i-can_do)+j, temp.pixels+(temp.w*temp.bpp*j));
op(img, (img->h-i-can_do)+j, temp.pixels+(temp.w*temp.bpp*j), data);
}
}
}
@ -443,7 +443,7 @@ void imlib_image_operation(image_t *img, const char *path, image_t *other, line_
ff_not_equal(NULL);
}
for (int i=0; i<img->h; i++) {
op(img, i, other->pixels + (img->w * img->bpp * i));
op(img, i, other->pixels + (img->w * img->bpp * i), data);
}
}
}
@ -687,8 +687,10 @@ void imlib_invert(image_t *img)
}
}
static void imlib_b_and_line_op(image_t *img, int line, uint8_t *other)
static void imlib_b_and_line_op(image_t *img, int line, uint8_t *other, void *data)
{
data = data;
if (IM_IS_GS(img)) {
uint8_t *pixels = img->pixels + (img->w * line);
for (int i=0; i<img->w; i++) {
@ -704,11 +706,13 @@ static void imlib_b_and_line_op(image_t *img, int line, uint8_t *other)
void imlib_b_and(image_t *img, const char *path, image_t *other)
{
imlib_image_operation(img, path, other, imlib_b_and_line_op);
imlib_image_operation(img, path, other, imlib_b_and_line_op, NULL);
}
static void imlib_b_nand_line_op(image_t *img, int line, uint8_t *other)
static void imlib_b_nand_line_op(image_t *img, int line, uint8_t *other, void *data)
{
data = data;
if (IM_IS_GS(img)) {
uint8_t *pixels = img->pixels + (img->w * line);
for (int i=0; i<img->w; i++) {
@ -724,11 +728,13 @@ static void imlib_b_nand_line_op(image_t *img, int line, uint8_t *other)
void imlib_b_nand(image_t *img, const char *path, image_t *other)
{
imlib_image_operation(img, path, other, imlib_b_nand_line_op);
imlib_image_operation(img, path, other, imlib_b_nand_line_op, NULL);
}
static void imlib_b_or_line_op(image_t *img, int line, uint8_t *other)
static void imlib_b_or_line_op(image_t *img, int line, uint8_t *other, void *data)
{
data = data;
if (IM_IS_GS(img)) {
uint8_t *pixels = img->pixels + (img->w * line);
for (int i=0; i<img->w; i++) {
@ -744,11 +750,13 @@ static void imlib_b_or_line_op(image_t *img, int line, uint8_t *other)
void imlib_b_or(image_t *img, const char *path, image_t *other)
{
imlib_image_operation(img, path, other, imlib_b_or_line_op);
imlib_image_operation(img, path, other, imlib_b_or_line_op, NULL);
}
static void imlib_b_nor_line_op(image_t *img, int line, uint8_t *other)
static void imlib_b_nor_line_op(image_t *img, int line, uint8_t *other, void *data)
{
data = data;
if (IM_IS_GS(img)) {
uint8_t *pixels = img->pixels + (img->w * line);
for (int i=0; i<img->w; i++) {
@ -764,11 +772,13 @@ static void imlib_b_nor_line_op(image_t *img, int line, uint8_t *other)
void imlib_b_nor(image_t *img, const char *path, image_t *other)
{
imlib_image_operation(img, path, other, imlib_b_nor_line_op);
imlib_image_operation(img, path, other, imlib_b_nor_line_op, NULL);
}
static void imlib_b_xor_line_op(image_t *img, int line, uint8_t *other)
static void imlib_b_xor_line_op(image_t *img, int line, uint8_t *other, void *data)
{
data = data;
if (IM_IS_GS(img)) {
uint8_t *pixels = img->pixels + (img->w * line);
for (int i=0; i<img->w; i++) {
@ -784,11 +794,13 @@ static void imlib_b_xor_line_op(image_t *img, int line, uint8_t *other)
void imlib_b_xor(image_t *img, const char *path, image_t *other)
{
imlib_image_operation(img, path, other, imlib_b_xor_line_op);
imlib_image_operation(img, path, other, imlib_b_xor_line_op, NULL);
}
static void imlib_b_xnor_line_op(image_t *img, int line, uint8_t *other)
static void imlib_b_xnor_line_op(image_t *img, int line, uint8_t *other, void *data)
{
data = data;
if (IM_IS_GS(img)) {
uint8_t *pixels = img->pixels + (img->w * line);
for (int i=0; i<img->w; i++) {
@ -804,7 +816,7 @@ static void imlib_b_xnor_line_op(image_t *img, int line, uint8_t *other)
void imlib_b_xnor(image_t *img, const char *path, image_t *other)
{
imlib_image_operation(img, path, other, imlib_b_xnor_line_op);
imlib_image_operation(img, path, other, imlib_b_xnor_line_op, NULL);
}
static void imlib_erode_dilate(image_t *img, int ksize, int threshold, int e_or_d)
@ -936,8 +948,10 @@ void imlib_negate(image_t *img)
}
}
static void imlib_difference_line_op(image_t *img, int line, uint8_t *other)
static void imlib_difference_line_op(image_t *img, int line, uint8_t *other, void *data)
{
data = data;
if (IM_IS_GS(img)) {
uint8_t *pixels = img->pixels + (img->w * line);
for (int i=0; i<img->w; i++) {
@ -957,11 +971,13 @@ static void imlib_difference_line_op(image_t *img, int line, uint8_t *other)
void imlib_difference(image_t *img, const char *path, image_t *other)
{
imlib_image_operation(img, path, other, imlib_difference_line_op);
imlib_image_operation(img, path, other, imlib_difference_line_op, NULL);
}
static void imlib_replace_line_op(image_t *img, int line, uint8_t *other)
static void imlib_replace_line_op(image_t *img, int line, uint8_t *other, void *data)
{
data = data;
if (IM_IS_GS(img)) {
uint8_t *pixels = img->pixels + (img->w * line);
memcpy(pixels, other, img->w * sizeof(uint8_t));
@ -973,17 +989,17 @@ static void imlib_replace_line_op(image_t *img, int line, uint8_t *other)
void imlib_replace(image_t *img, const char *path, image_t *other)
{
imlib_image_operation(img, path, other, imlib_replace_line_op);
imlib_image_operation(img, path, other, imlib_replace_line_op, NULL);
}
static uint32_t alpha_temp;
static void imlib_blend_line_op(image_t *img, int line, uint8_t *other)
static void imlib_blend_line_op(image_t *img, int line, uint8_t *other, void *data)
{
uint32_t alpha = (uint32_t) data;
if (IM_IS_GS(img)) {
uint8_t *pixels = img->pixels + (img->w * line);
for (int i=0; i<img->w; i++) {
pixels[i] = __SMUAD(alpha_temp,__PKHBT(pixels[i],other[i],16))>>8;
pixels[i] = __SMUAD(alpha,__PKHBT(pixels[i],other[i],16))>>8;
}
} else {
uint16_t *pixels = ((uint16_t *) img->pixels) + (img->w * line);
@ -992,9 +1008,9 @@ static void imlib_blend_line_op(image_t *img, int line, uint8_t *other)
uint32_t vr = __PKHBT(IM_R565(pixel), IM_R565(other_pixel), 16);
uint32_t vg = __PKHBT(IM_G565(pixel), IM_G565(other_pixel), 16);
uint32_t vb = __PKHBT(IM_B565(pixel), IM_B565(other_pixel), 16);
uint32_t r = __SMUAD(alpha_temp, vr)>>8;
uint32_t g = __SMUAD(alpha_temp, vg)>>8;
uint32_t b = __SMUAD(alpha_temp, vb)>>8;
uint32_t r = __SMUAD(alpha, vr)>>8;
uint32_t g = __SMUAD(alpha, vg)>>8;
uint32_t b = __SMUAD(alpha, vb)>>8;
pixels[i] = IM_RGB565(r, g, b);
}
}
@ -1002,8 +1018,7 @@ static void imlib_blend_line_op(image_t *img, int line, uint8_t *other)
void imlib_blend(image_t *img, const char *path, image_t *other, int alpha)
{
alpha_temp = __PKHBT((256-alpha), alpha, 16);
imlib_image_operation(img, path, other, imlib_blend_line_op);
imlib_image_operation(img, path, other, imlib_blend_line_op, (void *) __PKHBT((256-alpha), alpha, 16));
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -10,6 +10,8 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <limits.h>
#include <float.h>
#include <math.h>
#include <arm_math.h>
#include <ff.h>
@ -896,7 +898,7 @@ typedef struct img_read_settings {
save_image_format_t format;
} img_read_settings_t;
typedef void (*line_op_t)(image_t*, int, uint8_t*);
typedef void (*line_op_t)(image_t*, int, uint8_t*, void*);
typedef enum descriptor_type {
DESC_LBP,
@ -1059,7 +1061,7 @@ void jpeg_read_pixels(FIL *fp, image_t *img);
void jpeg_read(image_t *img, const char *path);
void jpeg_write(image_t *img, const char *path, int quality);
bool imlib_read_geometry(FIL *fp, image_t *img, const char *path, img_read_settings_t *rs);
void imlib_image_operation(image_t *img, const char *path, image_t *other, line_op_t op);
void imlib_image_operation(image_t *img, const char *path, image_t *other, line_op_t op, void *data);
void imlib_load_image(image_t *img, const char *path);
void imlib_save_image(image_t *img, const char *path, rectangle_t *roi, int quality);
void imlib_copy_image(image_t *dst, image_t *src, rectangle_t *roi);
@ -1211,6 +1213,7 @@ void imlib_rotation_corr(image_t *img, float x_rotation, float y_rotation,
float z_rotation, float x_translation, float y_translation,
float zoom);
// Statistics
void imlib_get_similarity(image_t *img, const char *path, image_t *other, float *avg, float *std, float *min, float *max);
void imlib_get_histogram(histogram_t *out, image_t *ptr, rectangle_t *roi);
void imlib_get_percentile(percentile_t *out, image_bpp_t bpp, histogram_t *ptr, float percentile);
void imlib_get_statistics(statistics_t *out, image_bpp_t bpp, histogram_t *ptr);

View File

@ -5,6 +5,140 @@
#include "imlib.h"
typedef struct imlib_similatiry_line_op_state {
int *sumBucketsOfX, *sumBucketsOfY, *sum2BucketsOfX, *sum2BucketsOfY, *sum2Buckets;
float similarity_sum, similarity_sum_2, similarity_min, similarity_max;
int lines_processed;
} imlib_similatiry_line_op_state_t;
void imlib_similarity_line_op(image_t *img, int line, uint8_t *other, void *data)
{
imlib_similatiry_line_op_state_t *state = (imlib_similatiry_line_op_state_t *) data;
float c1 = 0, c2 = 0;
switch(img->bpp) {
case IMAGE_BPP_BINARY: {
uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(img, line);
uint32_t *other_row_ptr = (uint32_t *) other;
for (int x = 0, xx = (img->w + 7) / 8; x < xx; x++) {
for (int i = 0, ii = IM_MIN((img->w - (x * 8)), 8); i < ii; i++) {
int pixel = IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x + i);
int other_pixel = IMAGE_GET_BINARY_PIXEL_FAST(other_row_ptr, x + i);
state->sumBucketsOfX[x] += pixel;
state->sumBucketsOfY[x] += other_pixel;
state->sum2BucketsOfX[x] += pixel * pixel;
state->sum2BucketsOfY[x] += other_pixel * other_pixel;
state->sum2Buckets[x] += pixel * other_pixel;
}
}
c1 = COLOR_BINARY_MAX * 0.01f;
c2 = COLOR_BINARY_MAX * 0.03f;
break;
}
case IMAGE_BPP_GRAYSCALE: {
uint8_t *row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(img, line);
uint8_t *other_row_ptr = (uint8_t *) other;
for (int x = 0, xx = (img->w + 7) / 8; x < xx; x++) {
for (int i = 0, ii = IM_MIN((img->w - (x * 8)), 8); i < ii; i++) {
int pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x + i);
int other_pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(other_row_ptr, x + i);
state->sumBucketsOfX[x] += pixel;
state->sumBucketsOfY[x] += other_pixel;
state->sum2BucketsOfX[x] += pixel * pixel;
state->sum2BucketsOfY[x] += other_pixel * other_pixel;
state->sum2Buckets[x] += pixel * other_pixel;
}
}
c1 = COLOR_GRAYSCALE_MAX * 0.01f;
c2 = COLOR_GRAYSCALE_MAX * 0.03f;
break;
}
case IMAGE_BPP_RGB565: {
uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(img, line);
uint16_t *other_row_ptr = (uint16_t *) other;
for (int x = 0, xx = (img->w + 7) / 8; x < xx; x++) {
for (int i = 0, ii = IM_MIN((img->w - (x * 8)), 8); i < ii; i++) {
int pixel = COLOR_RGB565_TO_L(IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x + i));
int other_pixel = COLOR_RGB565_TO_L(IMAGE_GET_RGB565_PIXEL_FAST(other_row_ptr, x + i));
state->sumBucketsOfX[x] += pixel;
state->sumBucketsOfY[x] += other_pixel;
state->sum2BucketsOfX[x] += pixel * pixel;
state->sum2BucketsOfY[x] += other_pixel * other_pixel;
state->sum2Buckets[x] += pixel * other_pixel;
}
}
c1 = COLOR_L_MAX * 0.01f;
c2 = COLOR_L_MAX * 0.03f;
break;
}
default: {
break;
}
}
// https://en.wikipedia.org/wiki/Structural_similarity
if (((state->lines_processed + 1) == img->h) || (!((state->lines_processed + 1) % 8))) {
for (int x = 0, xx = (img->w + 7) / 8; x < xx; x++) {
int w = IM_MIN((img->w - (x * 8)), 8);
int h = IM_MIN((img->h - ((state->lines_processed / 8) * 8)), 8);
int size = w * h;
int mx = state->sumBucketsOfX[x] / size;
int my = state->sumBucketsOfY[x] / size;
int vx = state->sum2BucketsOfX[x] - ((mx * state->sumBucketsOfX[x]) + (mx * state->sumBucketsOfX[x])) + (size * mx * mx);
int vy = state->sum2BucketsOfY[x] - ((my * state->sumBucketsOfY[x]) + (my * state->sumBucketsOfY[x])) + (size * my * my);
int vxy = state->sum2Buckets[x] - ((mx * state->sumBucketsOfY[x]) + (my * state->sumBucketsOfX[x])) + (size * mx * my);
float ssim = ( ((2*mx*my) + c1) * ((2*vxy) + c2) ) / ( ((mx*mx) + (my*my) + c1) * (vx + vy + c2) );
state->similarity_sum += ssim;
state->similarity_sum_2 += ssim * ssim;
state->similarity_min = IM_MIN(state->similarity_min, ssim);
state->similarity_max = IM_MAX(state->similarity_max, ssim);
state->sumBucketsOfX[x] = 0;
state->sumBucketsOfY[x] = 0;
state->sum2BucketsOfX[x] = 0;
state->sum2BucketsOfY[x] = 0;
state->sum2Buckets[x] = 0;
}
}
state->lines_processed += 1;
}
void imlib_get_similarity(image_t *img, const char *path, image_t *other, float *avg, float *std, float *min, float *max)
{
int h_blocks = (img->w + 7) / 8;
int v_blocks = (img->h + 7) / 8;
int blocks = h_blocks * v_blocks;
int int_h_blocks = h_blocks * sizeof(int);
imlib_similatiry_line_op_state_t state;
state.sumBucketsOfX = fb_alloc0(int_h_blocks);
state.sumBucketsOfY = fb_alloc0(int_h_blocks);
state.sum2BucketsOfX = fb_alloc0(int_h_blocks);
state.sum2BucketsOfY = fb_alloc0(int_h_blocks);
state.sum2Buckets = fb_alloc0(int_h_blocks);
state.similarity_sum = 0.0f;
state.similarity_sum_2 = 0.0f;
state.similarity_min = FLT_MAX;
state.similarity_max = FLT_MIN;
state.lines_processed = 0;
imlib_image_operation(img, path, other, imlib_similarity_line_op, (void *) &state);
*avg = state.similarity_sum / blocks;
*std = fast_sqrtf((state.similarity_sum_2 / blocks) - ((*avg) * (*avg)));
*min = state.similarity_min;
*max = state.similarity_max;
fb_free();
fb_free();
fb_free();
fb_free();
fb_free();
}
void imlib_get_histogram(histogram_t *out, image_t *ptr, rectangle_t *roi)
{
switch(ptr->bpp) {

View File

@ -1357,6 +1357,101 @@ static mp_obj_t py_image_mask_ellipse(mp_obj_t img_obj)
return img_obj;
}
// Similarity Object //
#define py_similarity_obj_size 4
typedef struct py_similarity_obj {
mp_obj_base_t base;
mp_obj_t avg, std, min, max;
} py_similarity_obj_t;
static void py_similarity_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind)
{
py_similarity_obj_t *self = self_in;
mp_printf(print,
"{mean:%f, stdev:%f, min:%f, max:%f}",
(double) mp_obj_get_float(self->avg),
(double) mp_obj_get_float(self->std),
(double) mp_obj_get_float(self->min),
(double) mp_obj_get_float(self->max));
}
static mp_obj_t py_similarity_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value)
{
if (value == MP_OBJ_SENTINEL) { // load
py_similarity_obj_t *self = self_in;
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
mp_bound_slice_t slice;
if (!mp_seq_get_fast_slice_indexes(py_similarity_obj_size, index, &slice)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "only slices with step=1 (aka None) are supported"));
}
mp_obj_tuple_t *result = mp_obj_new_tuple(slice.stop - slice.start, NULL);
mp_seq_copy(result->items, &(self->avg) + slice.start, result->len, mp_obj_t);
return result;
}
switch (mp_get_index(self->base.type, py_similarity_obj_size, index, false)) {
case 0: return self->avg;
case 1: return self->std;
case 2: return self->min;
case 3: return self->max;
}
}
return MP_OBJ_NULL; // op not supported
}
mp_obj_t py_similarity_mean(mp_obj_t self_in) { return ((py_similarity_obj_t *) self_in)->avg; }
mp_obj_t py_similarity_stdev(mp_obj_t self_in) { return ((py_similarity_obj_t *) self_in)->std; }
mp_obj_t py_similarity_min(mp_obj_t self_in) { return ((py_similarity_obj_t *) self_in)->min; }
mp_obj_t py_similarity_max(mp_obj_t self_in) { return ((py_similarity_obj_t *) self_in)->max; }
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_similarity_mean_obj, py_similarity_mean);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_similarity_stdev_obj, py_similarity_stdev);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_similarity_min_obj, py_similarity_min);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_similarity_max_obj, py_similarity_max);
STATIC const mp_rom_map_elem_t py_similarity_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_mean), MP_ROM_PTR(&py_similarity_mean_obj) },
{ MP_ROM_QSTR(MP_QSTR_stdev), MP_ROM_PTR(&py_similarity_stdev_obj) },
{ MP_ROM_QSTR(MP_QSTR_min), MP_ROM_PTR(&py_similarity_min_obj) },
{ MP_ROM_QSTR(MP_QSTR_max), MP_ROM_PTR(&py_similarity_max_obj) }
};
STATIC MP_DEFINE_CONST_DICT(py_similarity_locals_dict, py_similarity_locals_dict_table);
static const mp_obj_type_t py_similarity_type = {
{ &mp_type_type },
.name = MP_QSTR_similarity,
.print = py_similarity_print,
.subscr = py_similarity_subscr,
.locals_dict = (mp_obj_t) &py_similarity_locals_dict,
};
static mp_obj_t py_image_get_similarity(mp_obj_t img_obj, mp_obj_t other_obj)
{
image_t *arg_img = py_image_cobj(img_obj);
PY_ASSERT_TRUE_MSG(IM_IS_MUTABLE(arg_img), "Image format is not supported.");
float avg, std, min, max;
if (MP_OBJ_IS_STR(other_obj)) {
fb_alloc_mark();
imlib_get_similarity(arg_img, mp_obj_str_get_str(other_obj), NULL, &avg, &std, &min, &max);
fb_alloc_mark();
} else {
image_t *arg_other = py_image_cobj(other_obj);
fb_alloc_mark();
imlib_get_similarity(arg_img, NULL, arg_other, &avg, &std, &min, &max);
fb_alloc_free_till_mark();
}
py_similarity_obj_t *o = m_new_obj(py_similarity_obj_t);
o->base.type = &py_similarity_type;
o->avg = mp_obj_new_float(avg);
o->std = mp_obj_new_float(std);
o->min = mp_obj_new_float(min);
o->max = mp_obj_new_float(max);
return o;
}
// Statistics Object //
#define py_statistics_obj_size 24
typedef struct py_statistics_obj {
@ -3918,6 +4013,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_rotation_corr_obj, 1, py_image_rotati
#endif
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_mask_ellipse_obj, py_image_mask_ellipse);
/* Image Statistics */
STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_get_similarity_obj, py_image_get_similarity);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_get_histogram_obj, 1, py_image_get_histogram);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_get_statistics_obj, 1, py_image_get_statistics);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_get_regression_obj, 2, py_image_get_regression);
@ -4027,6 +4123,7 @@ static const mp_map_elem_t locals_dict_table[] = {
#endif
{MP_OBJ_NEW_QSTR(MP_QSTR_mask_ellipse), (mp_obj_t)&py_image_mask_ellipse_obj},
/* Image Statistics */
{MP_OBJ_NEW_QSTR(MP_QSTR_get_similarity), (mp_obj_t)&py_image_get_similarity_obj},
{MP_OBJ_NEW_QSTR(MP_QSTR_get_hist), (mp_obj_t)&py_image_get_histogram_obj},
{MP_OBJ_NEW_QSTR(MP_QSTR_get_histogram), (mp_obj_t)&py_image_get_histogram_obj},
{MP_OBJ_NEW_QSTR(MP_QSTR_histogram), (mp_obj_t)&py_image_get_histogram_obj},

View File

@ -360,6 +360,15 @@ Q(x_translation)
Q(y_translation)
// duplicate Q(zoom)
// Structural Similarity
Q(get_similarity)
// Similarity Object
Q(similarity)
// duplicate Q(mean)
Q(stdev)
// duplicate Q(min)
// duplicate Q(max)
// Get Histogram
Q(get_hist)
Q(get_histogram)
@ -398,7 +407,7 @@ Q(b_value)
// duplicate Q(mean)
// duplicate Q(median)
// duplicate Q(mode)
Q(stdev)
// duplicate Q(stdev)
// duplicate Q(min)
// duplicate Q(max)
Q(lq)

View File

@ -0,0 +1,35 @@
# Structural Similarity (SSIM) Example
#
# Note: You will need an SD card to run this example.
#
# This example shows off how to use the SSIM algorithm on your OpenMV Cam
# to detect differences between two images. The SSIM algorithm compares
# 8x8 blocks of pixels between two images to determine a similarity
# score between two images.
import sensor, image, pyb, os, time
# The image has likely changed if the sim.min() is lower than this.
MIN_TRIGGER_THRESHOLD = -0.4
sensor.reset() # Initialize the camera sensor.
sensor.set_pixformat(sensor.RGB565) # or sensor.GRAYSCALE
sensor.set_framesize(sensor.QVGA) # or sensor.QQVGA (or others)
sensor.skip_frames(time = 2000) # Let new settings take affect.
sensor.set_auto_whitebal(False) # Turn off white balance.
clock = time.clock() # Tracks FPS.
if not "temp" in os.listdir(): os.mkdir("temp") # Make a temp directory
print("About to save background image...")
sensor.skip_frames(time = 2000) # Give the user time to get ready.
sensor.snapshot().save("temp/bg.bmp")
print("Saved background image!")
while(True):
clock.tick() # Track elapsed milliseconds between snapshots().
img = sensor.snapshot() # Take a picture and return the image.
sim = img.get_similarity("temp/bg.bmp")
change = "- Change -" if sim.min() < MIN_TRIGGER_THRESHOLD else "- No Change -"
print(clock.fps(), change, sim)