This commit is contained in:
iabdalkader 2017-01-08 17:07:07 +02:00
commit 9ac0d0b0dd
4 changed files with 1205 additions and 261 deletions

View File

@ -722,39 +722,6 @@ typedef struct simple_color {
}
simple_color_t;
typedef struct statistics {
uint8_t g_mean;
int8_t l_mean, a_mean, b_mean;
uint8_t g_median;
int8_t l_median, a_median, b_median;
uint8_t g_mode;
int8_t l_mode, a_mode, b_mode;
uint8_t g_st_dev;
int8_t l_st_dev, a_st_dev, b_st_dev;
uint8_t g_min;
int8_t l_min, a_min, b_min;
uint8_t g_max;
int8_t l_max, a_max, b_max;
uint8_t g_lower_q;
int8_t l_lower_q, a_lower_q, b_lower_q;
uint8_t g_upper_q;
int8_t l_upper_q, a_upper_q, b_upper_q;
} statistics_t;
typedef struct color_blob { // organized this way to pack it...
int16_t x; // rect - 0
int16_t y; // rect - 1
int16_t w; // rect - 2
int16_t h; // rect - 3
int16_t cx; // centroid - 5
int16_t cy; // centroid - 6
float rotation; // rotation - 7
uint16_t pixels; // number of pixels in merged blobs - 4
uint16_t count; // number of blobs merged into this blob - 9
uint32_t code; // color code index bits of merged blobs - 8
}
color_blob_t;
typedef struct image {
int w;
int h;
@ -888,6 +855,27 @@ typedef enum jpeg_subsample {
JPEG_SUBSAMPLE_2x2 = 0x22, // 2x2 chroma subsampling
} jpeg_subsample_t;
typedef struct histogram {
int LBinCount;
float *LBins;
int ABinCount;
float *ABins;
int BBinCount;
float *BBins;
} histogram_t;
typedef struct percentile {
uint8_t LValue;
int8_t AValue;
int8_t BValue;
} percentile_t;
typedef struct statistics {
uint8_t LMean, LMedian, LMode, LSTDev, LMin, LMax, LLQ, LUQ;
int8_t AMean, AMedian, AMode, ASTDev, AMin, AMax, ALQ, AUQ;
int8_t BMean, BMedian, BMode, BSTDev, BMin, BMax, BLQ, BUQ;
} statistics_t;
typedef struct find_blobs_list_lnk_data
{
rectangle_t rect;
@ -992,8 +980,6 @@ void imlib_blend(image_t *img, const char *path, image_t *other, int alpha);
void imlib_morph(image_t *img, const int ksize, const int8_t *krn, const float m, const int b);
/* Image Statistics */
int32_t *imlib_histogram(image_t *img, rectangle_t *r);
void imlib_statistics(image_t *img, rectangle_t *r, statistics_t *out);
int imlib_image_mean(image_t *src); // grayscale only
int imlib_image_std(image_t *src); // grayscale only
@ -1077,6 +1063,10 @@ void imlib_find_hog(image_t *src, rectangle_t *roi, int cell_size);
// Lens correction
void imlib_lens_corr(image_t *src, float strength);
// Stats
void imlib_get_histogram(histogram_t *out, new_image_t *ptr, rectangle_t *roi);
void imlib_get_percentile(percentile_t *out, new_image_type_t type, histogram_t *ptr, float percentile);
void imlib_get_statistics(statistics_t *out, new_image_type_t type, histogram_t *ptr);
// Color Tracking
void imlib_find_blobs(list_t *out, new_image_t *ptr, rectangle_t *roi,
list_t *thresholds, bool invert, unsigned int area_threshold, unsigned int pixels_threshold,

View File

@ -1,221 +1,427 @@
/*
* This file is part of the OpenMV project.
* Copyright (c) 2013-2016 Kwabena W. Agyeman <kwagyeman@openmv.io>
/* This file is part of the OpenMV project.
* Copyright (c) 2013-2017 Ibrahim Abdelkader <iabdalkader@openmv.io> & Kwabena W. Agyeman <kwagyeman@openmv.io>
* This work is licensed under the MIT license, see the file LICENSE for details.
*
* Generic image statistics functions.
*
*/
#include <string.h>
#include "imlib.h"
#include "fb_alloc.h"
int32_t *imlib_histogram(image_t *img, rectangle_t *r)
#include "imlib.h"
void imlib_get_histogram(histogram_t *out, new_image_t *ptr, rectangle_t *roi)
{
rectangle_t rect;
if (!rectangle_subimg(img, r, &rect)) {
return NULL;
}
int32_t *histogram;
if (IM_IS_GS(img)) {
histogram = fb_alloc0(IM_G_HIST_SIZE * sizeof(int32_t));
} else {
histogram = fb_alloc0((IM_L_HIST_SIZE * sizeof(int32_t)) +
(IM_A_HIST_SIZE * sizeof(int32_t)) +
(IM_B_HIST_SIZE * sizeof(int32_t)));
}
if (IM_IS_GS(img)) {
for (int i = 0; i < rect.h; i++) {
for (int j = 0; j < rect.w; j++) {
int x = (rect.x + j);
int y = (rect.y + i);
histogram[IM_GET_GS_PIXEL(img, x, y)]++;
switch(ptr->type) {
case IMAGE_TYPE_BINARY: {
memset(out->LBins, 0, out->LBinCount * sizeof(uint32_t));
float mult = (out->LBinCount - 1) / ((float) (COLOR_BINARY_MAX - COLOR_BINARY_MIN));
for (int y = roi->y, yy = roi->y + roi->h; y < yy; y++) {
uint32_t *row_ptr = IMAGE_COMPUTE_BINARY_PIXEL_ROW_PTR(ptr, y);
for (int x = roi->x, xx = roi->x + roi->w; x < xx; x++) {
int pixel = IMAGE_GET_BINARY_PIXEL_FAST(row_ptr, x);
((uint32_t *) out->LBins)[fast_roundf((pixel - COLOR_BINARY_MIN) * mult)]++;
}
}
float pixels = roi->w * roi->h;
for (int i = 0, j = out->LBinCount; i < j; i++) {
out->LBins[i] = ((uint32_t *) out->LBins)[i] / pixels;
}
break;
}
} else {
for (int i = 0; i < rect.h; i++) {
for (int j = 0; j < rect.w; j++) {
int x = (rect.x + j);
int y = (rect.y + i);
const int pixel = IM_GET_RGB565_PIXEL(img, x, y);
histogram[IM_RGB5652L(pixel) + IM_L_HIST_OFFSET + 128]++;
histogram[IM_RGB5652A(pixel) + IM_A_HIST_OFFSET + 128]++;
histogram[IM_RGB5652B(pixel) + IM_B_HIST_OFFSET + 128]++;
case IMAGE_TYPE_GRAYSCALE: {
memset(out->LBins, 0, out->LBinCount * sizeof(uint32_t));
float mult = (out->LBinCount - 1) / ((float) (COLOR_GRAYSCALE_MAX - COLOR_GRAYSCALE_MIN));
for (int y = roi->y, yy = roi->y + roi->h; y < yy; y++) {
uint8_t *row_ptr = IMAGE_COMPUTE_GRAYSCALE_PIXEL_ROW_PTR(ptr, y);
for (int x = roi->x, xx = roi->x + roi->w; x < xx; x++) {
int pixel = IMAGE_GET_GRAYSCALE_PIXEL_FAST(row_ptr, x);
((uint32_t *) out->LBins)[fast_roundf((pixel - COLOR_GRAYSCALE_MIN) * mult)]++;
}
}
float pixels = roi->w * roi->h;
for (int i = 0, j = out->LBinCount; i < j; i++) {
out->LBins[i] = ((uint32_t *) out->LBins)[i] / pixels;
}
break;
}
case IMAGE_TYPE_RGB565: {
memset(out->LBins, 0, out->LBinCount * sizeof(uint32_t));
memset(out->ABins, 0, out->ABinCount * sizeof(uint32_t));
memset(out->BBins, 0, out->BBinCount * sizeof(uint32_t));
float l_mult = (out->LBinCount - 1) / ((float) (COLOR_L_MAX - COLOR_L_MIN));
float a_mult = (out->ABinCount - 1) / ((float) (COLOR_A_MAX - COLOR_A_MIN));
float b_mult = (out->BBinCount - 1) / ((float) (COLOR_B_MAX - COLOR_B_MIN));
for (int y = roi->y, yy = roi->y + roi->h; y < yy; y++) {
uint16_t *row_ptr = IMAGE_COMPUTE_RGB565_PIXEL_ROW_PTR(ptr, y);
for (int x = roi->x, xx = roi->x + roi->w; x < xx; x++) {
int pixel = IMAGE_GET_RGB565_PIXEL_FAST(row_ptr, x);
((uint32_t *) out->LBins)[fast_roundf((COLOR_RGB565_TO_L(pixel) - COLOR_L_MIN) * l_mult)]++;
((uint32_t *) out->ABins)[fast_roundf((COLOR_RGB565_TO_A(pixel) - COLOR_A_MIN) * a_mult)]++;
((uint32_t *) out->BBins)[fast_roundf((COLOR_RGB565_TO_B(pixel) - COLOR_B_MIN) * b_mult)]++;
}
}
float pixels = roi->w * roi->h;
for (int i = 0, j = out->LBinCount; i < j; i++) {
out->LBins[i] = ((uint32_t *) out->LBins)[i] / pixels;
}
for (int i = 0, j = out->ABinCount; i < j; i++) {
out->ABins[i] = ((uint32_t *) out->ABins)[i] / pixels;
}
for (int i = 0, j = out->BBinCount; i < j; i++) {
out->BBins[i] = ((uint32_t *) out->BBins)[i] / pixels;
}
break;
}
default: {
break;
}
}
return histogram;
}
void imlib_statistics(image_t *img, rectangle_t *r, statistics_t *out)
void imlib_get_percentile(percentile_t *out, new_image_type_t type, histogram_t *ptr, float percentile)
{
memset(out, 0, sizeof(percentile_t));
switch(type) {
case IMAGE_TYPE_BINARY: {
float mult = (COLOR_BINARY_MAX - COLOR_BINARY_MIN) / ((float) (ptr->LBinCount - 1));
float median_count = 0;
for (int i = 0, j = ptr->LBinCount; i < j; i++) {
if ((median_count < percentile) && (percentile <= (median_count + ptr->LBins[i]))) {
out->LValue = fast_roundf((i * mult) + COLOR_BINARY_MIN);
break;
}
median_count += ptr->LBins[i];
}
break;
}
case IMAGE_TYPE_GRAYSCALE: {
float mult = (COLOR_GRAYSCALE_MAX - COLOR_GRAYSCALE_MIN) / ((float) (ptr->LBinCount - 1));
float median_count = 0;
for (int i = 0, j = ptr->LBinCount; i < j; i++) {
if ((median_count < percentile) && (percentile <= (median_count + ptr->LBins[i]))) {
out->LValue = fast_roundf((i * mult) + COLOR_GRAYSCALE_MIN);
break;
}
median_count += ptr->LBins[i];
}
break;
}
case IMAGE_TYPE_RGB565: {
{
float mult = (COLOR_L_MAX - COLOR_L_MIN) / ((float) (ptr->LBinCount - 1));
float median_count = 0;
for (int i = 0, j = ptr->LBinCount; i < j; i++) {
if ((median_count < percentile) && (percentile <= (median_count + ptr->LBins[i]))) {
out->LValue = fast_roundf((i * mult) + COLOR_L_MIN);
break;
}
median_count += ptr->LBins[i];
}
}
{
float mult = (COLOR_A_MAX - COLOR_A_MIN) / ((float) (ptr->ABinCount - 1));
float median_count = 0;
for (int i = 0, j = ptr->ABinCount; i < j; i++) {
if ((median_count < percentile) && (percentile <= (median_count + ptr->ABins[i]))) {
out->AValue = fast_roundf((i * mult) + COLOR_A_MIN);
break;
}
median_count += ptr->ABins[i];
}
}
{
float mult = (COLOR_B_MAX - COLOR_B_MIN) / ((float) (ptr->BBinCount - 1));
float median_count = 0;
for (int i = 0, j = ptr->BBinCount; i < j; i++) {
if ((median_count < percentile) && (percentile <= (median_count + ptr->BBins[i]))) {
out->BValue = fast_roundf((i * mult) + COLOR_A_MIN);
break;
}
median_count += ptr->BBins[i];
}
}
break;
}
default: {
break;
}
}
}
void imlib_get_statistics(statistics_t *out, new_image_type_t type, histogram_t *ptr)
{
memset(out, 0, sizeof(statistics_t));
int32_t *histogram = imlib_histogram(img, r);
if (!histogram) {
return;
}
if (IM_IS_GS(img)) {
int sum = 0, avg = 0;
int mode_count = -1;
bool min_flag = false;
for (int i = IM_G_HIST_OFFSET; i < (IM_G_HIST_OFFSET + IM_G_HIST_SIZE); i++) {
sum += histogram[i];
avg += (i-IM_G_HIST_OFFSET) * histogram[i];
if (histogram[i] > mode_count) {
mode_count = histogram[i];
out->g_mode = (i-IM_G_HIST_OFFSET);
}
if (histogram[i] && (!min_flag)) {
min_flag = true;
out->g_min = (i-IM_G_HIST_OFFSET);
}
if (histogram[i]) {
out->g_max = (i-IM_G_HIST_OFFSET);
}
}
out->g_mean = avg / sum;
// lower_q = 1/4th, median = 1/2, upper_q = 3/4th
int lq = (sum+3)/4, mid = (sum+1)/2, uq = ((sum*3)+3)/4;
int st_dev_count = 0, median_count = 0;
for (int i = IM_G_HIST_OFFSET; i < (IM_G_HIST_OFFSET + IM_G_HIST_SIZE); i++) {
st_dev_count += histogram[i] *
((i-IM_G_HIST_OFFSET)-out->g_mean) *
((i-IM_G_HIST_OFFSET)-out->g_mean);
if ((median_count<lq) && (lq<=(median_count+histogram[i]))) {
out->g_lower_q = (i-IM_G_HIST_OFFSET);
}
if ((median_count<mid) && (mid<=(median_count+histogram[i]))) {
out->g_median = (i-IM_G_HIST_OFFSET);
}
if ((median_count<uq) && (uq<=(median_count+histogram[i]))) {
out->g_upper_q = (i-IM_G_HIST_OFFSET);
}
median_count += histogram[i];
}
out->g_st_dev = fast_sqrtf(st_dev_count / sum);
} else {
{
int sum = 0, avg = 0;
int mode_count = -1;
switch(type) {
case IMAGE_TYPE_BINARY: {
float mult = (COLOR_BINARY_MAX - COLOR_BINARY_MIN) / ((float) (ptr->LBinCount - 1));
float avg = 0;
float stdev = 0;
float median_count = 0;
float mode_count = 0;
bool min_flag = false;
for (int i = IM_L_HIST_OFFSET; i < (IM_L_HIST_OFFSET + IM_L_HIST_SIZE); i++) {
sum += histogram[i];
avg += (i-IM_L_HIST_OFFSET-128) * histogram[i];
if (histogram[i] > mode_count) {
mode_count = histogram[i];
out->l_mode = (i-IM_L_HIST_OFFSET-128);
for (int i = 0, j = ptr->LBinCount; i < j; i++) {
float value_f = (i * mult) + COLOR_BINARY_MIN;
int value = fast_roundf(value_f);
avg += value_f * ptr->LBins[i];
stdev += value_f * value_f * ptr->LBins[i];
if ((median_count < 0.25f) && (0.25f <= (median_count + ptr->LBins[i]))) {
out->LLQ = value;
}
if (histogram[i] && (!min_flag)) {
if ((median_count < 0.5f) && (0.5f <= (median_count + ptr->LBins[i]))) {
out->LMedian = value;
}
if ((median_count < 0.75f) && (0.75f <= (median_count + ptr->LBins[i]))) {
out->LUQ = value;
}
if (ptr->LBins[i] > mode_count) {
mode_count = ptr->LBins[i];
out->LMode = value;
}
if ((ptr->LBins[i] > 0.0f) && (!min_flag)) {
min_flag = true;
out->l_min = (i-IM_L_HIST_OFFSET-128);
out->LMin = value;
}
if (histogram[i]) {
out->l_max = (i-IM_L_HIST_OFFSET-128);
if (ptr->LBins[i] > 0.0f) {
out->LMax = value;
}
median_count += ptr->LBins[i];
}
out->l_mean = avg / sum;
// lower_q = 1/4th, median = 1/2, upper_q = 3/4th
int lq = (sum+3)/4, mid = (sum+1)/2, uq = ((sum*3)+3)/4;
int st_dev_count = 0, median_count = 0;
for (int i = IM_L_HIST_OFFSET; i < (IM_L_HIST_OFFSET + IM_L_HIST_SIZE); i++) {
st_dev_count += histogram[i] *
((i-IM_L_HIST_OFFSET-128)-out->l_mean) *
((i-IM_L_HIST_OFFSET-128)-out->l_mean);
if ((median_count<lq) && (lq<=(median_count+histogram[i]))) {
out->l_lower_q = (i-IM_L_HIST_OFFSET-128);
}
if ((median_count<mid) && (mid<=(median_count+histogram[i]))) {
out->l_median = (i-IM_L_HIST_OFFSET-128);
}
if ((median_count<uq) && (uq<=(median_count+histogram[i]))) {
out->l_upper_q = (i-IM_L_HIST_OFFSET-128);
}
median_count += histogram[i];
}
out->l_st_dev = fast_sqrtf(st_dev_count / sum);
out->LMean = fast_roundf(avg);
out->LSTDev = fast_roundf(fast_sqrtf(stdev - (avg * avg)));
break;
}
////////////////////////////////////////////////////////////////////////
{
int sum = 0, avg = 0;
int mode_count = -1;
case IMAGE_TYPE_GRAYSCALE: {
float mult = (COLOR_GRAYSCALE_MAX - COLOR_GRAYSCALE_MIN) / ((float) (ptr->LBinCount - 1));
float avg = 0;
float stdev = 0;
float median_count = 0;
float mode_count = 0;
bool min_flag = false;
for (int i = IM_A_HIST_OFFSET; i < (IM_A_HIST_OFFSET + IM_A_HIST_SIZE); i++) {
sum += histogram[i];
avg += (i-IM_A_HIST_OFFSET-128) * histogram[i];
if (histogram[i] > mode_count) {
mode_count = histogram[i];
out->a_mode = (i-IM_A_HIST_OFFSET-128);
for (int i = 0, j = ptr->LBinCount; i < j; i++) {
float value_f = (i * mult) + COLOR_GRAYSCALE_MIN;
int value = fast_roundf(value_f);
avg += value_f * ptr->LBins[i];
stdev += value_f * value_f * ptr->LBins[i];
if ((median_count < 0.25f) && (0.25f <= (median_count + ptr->LBins[i]))) {
out->LLQ = value;
}
if (histogram[i] && (!min_flag)) {
if ((median_count < 0.5f) && (0.5f <= (median_count + ptr->LBins[i]))) {
out->LMedian = value;
}
if ((median_count < 0.75f) && (0.75f <= (median_count + ptr->LBins[i]))) {
out->LUQ = value;
}
if (ptr->LBins[i] > mode_count) {
mode_count = ptr->LBins[i];
out->LMode = value;
}
if ((ptr->LBins[i] > 0.0f) && (!min_flag)) {
min_flag = true;
out->a_min = (i-IM_A_HIST_OFFSET-128);
out->LMin = value;
}
if (histogram[i]) {
out->a_max = (i-IM_A_HIST_OFFSET-128);
if (ptr->LBins[i] > 0.0f) {
out->LMax = value;
}
median_count += ptr->LBins[i];
}
out->a_mean = avg / sum;
// lower_q = 1/4th, median = 1/2, upper_q = 3/4th
int lq = (sum+3)/4, mid = (sum+1)/2, uq = ((sum*3)+3)/4;
int st_dev_count = 0, median_count = 0;
for (int i = IM_A_HIST_OFFSET; i < (IM_A_HIST_OFFSET + IM_A_HIST_SIZE); i++) {
st_dev_count += histogram[i] *
((i-IM_A_HIST_OFFSET-128)-out->l_mean) *
((i-IM_A_HIST_OFFSET-128)-out->l_mean);
if ((median_count<lq) && (lq<=(median_count+histogram[i]))) {
out->a_lower_q = (i-IM_A_HIST_OFFSET-128);
}
if ((median_count<mid) && (mid<=(median_count+histogram[i]))) {
out->a_median = (i-IM_A_HIST_OFFSET-128);
}
if ((median_count<uq) && (uq<=(median_count+histogram[i]))) {
out->a_upper_q = (i-IM_A_HIST_OFFSET-128);
}
median_count += histogram[i];
}
out->a_st_dev = fast_sqrtf(st_dev_count / sum);
out->LMean = fast_roundf(avg);
out->LSTDev = fast_roundf(fast_sqrtf(stdev - (avg * avg)));
break;
}
////////////////////////////////////////////////////////////////////////
{
int sum = 0, avg = 0;
int mode_count = -1;
bool min_flag = false;
for (int i = IM_B_HIST_OFFSET; i < (IM_B_HIST_OFFSET + IM_B_HIST_SIZE); i++) {
sum += histogram[i];
avg += (i-IM_B_HIST_OFFSET-128) * histogram[i];
if (histogram[i] > mode_count) {
mode_count = histogram[i];
out->b_mode = (i-IM_B_HIST_OFFSET-128);
}
if (histogram[i] && (!min_flag)) {
min_flag = true;
out->b_min = (i-IM_B_HIST_OFFSET-128);
}
if (histogram[i]) {
out->b_max = (i-IM_B_HIST_OFFSET-128);
case IMAGE_TYPE_RGB565: {
{
float mult = (COLOR_L_MAX - COLOR_L_MIN) / ((float) (ptr->LBinCount - 1));
float avg = 0;
float stdev = 0;
float median_count = 0;
float mode_count = 0;
bool min_flag = false;
for (int i = 0, j = ptr->LBinCount; i < j; i++) {
float value_f = (i * mult) + COLOR_L_MIN;
int value = fast_roundf(value_f);
avg += value_f * ptr->LBins[i];
stdev += value_f * value_f * ptr->LBins[i];
if ((median_count < 0.25f) && (0.25f <= (median_count + ptr->LBins[i]))) {
out->LLQ = value;
}
if ((median_count < 0.5f) && (0.5f <= (median_count + ptr->LBins[i]))) {
out->LMedian = value;
}
if ((median_count < 0.75f) && (0.75f <= (median_count + ptr->LBins[i]))) {
out->LUQ = value;
}
if (ptr->LBins[i] > mode_count) {
mode_count = ptr->LBins[i];
out->LMode = value;
}
if ((ptr->LBins[i] > 0.0f) && (!min_flag)) {
min_flag = true;
out->LMin = value;
}
if (ptr->LBins[i] > 0.0f) {
out->LMax = value;
}
median_count += ptr->LBins[i];
}
out->LMean = fast_roundf(avg);
out->LSTDev = fast_roundf(fast_sqrtf(stdev - (avg * avg)));
}
out->b_mean = avg / sum;
// lower_q = 1/4th, median = 1/2, upper_q = 3/4th
int lq = (sum+3)/4, mid = (sum+1)/2, uq = ((sum*3)+3)/4;
int st_dev_count = 0, median_count = 0;
for (int i = IM_B_HIST_OFFSET; i < (IM_B_HIST_OFFSET + IM_B_HIST_SIZE); i++) {
st_dev_count += histogram[i] *
((i-IM_B_HIST_OFFSET-128)-out->l_mean) *
((i-IM_B_HIST_OFFSET-128)-out->l_mean);
if ((median_count<lq) && (lq<=(median_count+histogram[i]))) {
out->b_lower_q = (i-IM_B_HIST_OFFSET-128);
{
float mult = (COLOR_A_MAX - COLOR_A_MIN) / ((float) (ptr->ABinCount - 1));
float avg = 0;
float stdev = 0;
float median_count = 0;
float mode_count = 0;
bool min_flag = false;
for (int i = 0, j = ptr->ABinCount; i < j; i++) {
float value_f = (i * mult) + COLOR_A_MIN;
int value = fast_roundf(value_f);
avg += value_f * ptr->ABins[i];
stdev += value_f * value_f * ptr->ABins[i];
if ((median_count < 0.25f) && (0.25f <= (median_count + ptr->ABins[i]))) {
out->ALQ = value;
}
if ((median_count < 0.5f) && (0.5f <= (median_count + ptr->ABins[i]))) {
out->AMedian = value;
}
if ((median_count < 0.75f) && (0.75f <= (median_count + ptr->ABins[i]))) {
out->AUQ = value;
}
if (ptr->ABins[i] > mode_count) {
mode_count = ptr->ABins[i];
out->AMode = value;
}
if ((ptr->ABins[i] > 0.0f) && (!min_flag)) {
min_flag = true;
out->AMin = value;
}
if (ptr->ABins[i] > 0.0f) {
out->AMax = value;
}
median_count += ptr->ABins[i];
}
if ((median_count<mid) && (mid<=(median_count+histogram[i]))) {
out->b_median = (i-IM_B_HIST_OFFSET-128);
}
if ((median_count<uq) && (uq<=(median_count+histogram[i]))) {
out->b_upper_q = (i-IM_B_HIST_OFFSET-128);
}
median_count += histogram[i];
out->AMean = fast_roundf(avg);
out->ASTDev = fast_roundf(fast_sqrtf(stdev - (avg * avg)));
}
out->b_st_dev = fast_sqrtf(st_dev_count / sum);
{
float mult = (COLOR_B_MAX - COLOR_B_MIN) / ((float) (ptr->BBinCount - 1));
float avg = 0;
float stdev = 0;
float median_count = 0;
float mode_count = 0;
bool min_flag = false;
for (int i = 0, j = ptr->BBinCount; i < j; i++) {
float value_f = (i * mult) + COLOR_B_MIN;
int value = fast_roundf(value_f);
avg += value_f * ptr->BBins[i];
stdev += value_f * value_f * ptr->BBins[i];
if ((median_count < 0.25f) && (0.25f <= (median_count + ptr->BBins[i]))) {
out->BLQ = value;
}
if ((median_count < 0.5f) && (0.5f <= (median_count + ptr->BBins[i]))) {
out->BMedian = value;
}
if ((median_count < 0.75f) && (0.75f <= (median_count + ptr->BBins[i]))) {
out->BUQ = value;
}
if (ptr->BBins[i] > mode_count) {
mode_count = ptr->BBins[i];
out->BMode = value;
}
if ((ptr->BBins[i] > 0.0f) && (!min_flag)) {
min_flag = true;
out->BMin = value;
}
if (ptr->BBins[i] > 0.0f) {
out->BMax = value;
}
median_count += ptr->BBins[i];
}
out->BMean = fast_roundf(avg);
out->BSTDev = fast_roundf(fast_sqrtf(stdev - (avg * avg)));
}
break;
}
default: {
break;
}
}
fb_free();
}

View File

@ -762,40 +762,6 @@ static mp_obj_t py_image_morph(uint n_args, const mp_obj_t *args, mp_map_t *kw_a
return args[0];
}
static mp_obj_t py_image_statistics(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
image_t *arg_img = py_image_cobj(args[0]);
PY_ASSERT_FALSE_MSG(IM_IS_JPEG(arg_img),
"Operation not supported on JPEG");
rectangle_t arg_r;
py_helper_lookup_rectangle(kw_args, arg_img, &arg_r);
statistics_t out;
imlib_statistics(arg_img, &arg_r, &out);
if (IM_IS_GS(arg_img)) {
return mp_obj_new_tuple(8, (mp_obj_t[8])
{mp_obj_new_int(out.g_mean), mp_obj_new_int(out.g_median),
mp_obj_new_int(out.g_mode), mp_obj_new_int(out.g_st_dev),
mp_obj_new_int(out.g_min), mp_obj_new_int(out.g_max),
mp_obj_new_int(out.g_lower_q), mp_obj_new_int(out.g_upper_q)});
} else {
return mp_obj_new_tuple(24, (mp_obj_t[24])
{mp_obj_new_int(out.l_mean), mp_obj_new_int(out.l_median),
mp_obj_new_int(out.l_mode), mp_obj_new_int(out.l_st_dev),
mp_obj_new_int(out.l_min), mp_obj_new_int(out.l_max),
mp_obj_new_int(out.l_lower_q), mp_obj_new_int(out.l_upper_q),
mp_obj_new_int(out.a_mean), mp_obj_new_int(out.a_median),
mp_obj_new_int(out.a_mode), mp_obj_new_int(out.a_st_dev),
mp_obj_new_int(out.a_min), mp_obj_new_int(out.a_max),
mp_obj_new_int(out.a_lower_q), mp_obj_new_int(out.a_upper_q),
mp_obj_new_int(out.b_mean), mp_obj_new_int(out.b_median),
mp_obj_new_int(out.b_mode), mp_obj_new_int(out.b_st_dev),
mp_obj_new_int(out.b_min), mp_obj_new_int(out.b_max),
mp_obj_new_int(out.b_lower_q), mp_obj_new_int(out.b_upper_q)});
}
}
static mp_obj_t py_image_midpoint(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
image_t *arg_img = py_image_cobj(args[0]);
@ -899,6 +865,721 @@ static mp_obj_t py_image_mask_ellipse(mp_obj_t img_obj)
return img_obj;
}
// Histogram Object //
#define py_histogram_obj_size 6
typedef struct py_histogram_obj {
mp_obj_base_t base;
new_image_type_t type;
mp_obj_t LBinCount, LBins, ABinCount, ABins, BBinCount, BBins;
} py_histogram_obj_t;
// Percentile Object //
#define py_percentile_obj_size 3
typedef struct py_percentile_obj {
mp_obj_base_t base;
new_image_type_t type;
mp_obj_t LValue, AValue, BValue;
} py_percentile_obj_t;
// Statistics Object //
#define py_statistics_obj_size 24
typedef struct py_statistics_obj {
mp_obj_base_t base;
new_image_type_t type;
mp_obj_t LMean, LMedian, LMode, LSTDev, LMin, LMax, LLQ, LUQ, AMean, AMedian, AMode, ASTDev, AMin, AMax, ALQ, AUQ, BMean, BMedian, BMode, BSTDev, BMin, BMax, BLQ, BUQ;
} py_statistics_obj_t;
static void py_histogram_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind)
{
py_histogram_obj_t *self = self_in;
switch(self->type) {
case IMAGE_TYPE_BINARY: {
mp_printf(print, "{bin_count:%d, bins:", mp_obj_get_int(self->LBinCount));
mp_obj_print_helper(print, self->LBins, kind);
mp_printf(print, "}");
break;
}
case IMAGE_TYPE_GRAYSCALE: {
mp_printf(print, "{bin_count:%d, bins:", mp_obj_get_int(self->LBinCount));
mp_obj_print_helper(print, self->LBins, kind);
mp_printf(print, "}");
break;
}
case IMAGE_TYPE_RGB565: {
mp_printf(print, "{l_bin_count:%d, l_bins:", mp_obj_get_int(self->LBinCount));
mp_obj_print_helper(print, self->LBins, kind);
mp_printf(print, ", a_bin_count:%d, a_bins:", mp_obj_get_int(self->ABinCount));
mp_obj_print_helper(print, self->ABins, kind);
mp_printf(print, ", b_bin_count:%d, b_bins:", mp_obj_get_int(self->BBinCount));
mp_obj_print_helper(print, self->BBins, kind);
mp_printf(print, "}");
break;
}
default: {
mp_printf(print, "{}");
break;
}
}
}
static mp_obj_t py_histogram_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value)
{
if (value == MP_OBJ_SENTINEL) { // load
py_histogram_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_histogram_obj_size, index, &slice)) {
mp_not_implemented("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->LBinCount) + slice.start, result->len, mp_obj_t);
return result;
}
switch (mp_get_index(self->base.type, py_histogram_obj_size, index, false)) {
case 0: return self->LBinCount;
case 1: return self->LBins;
case 2: return self->ABinCount;
case 3: return self->ABins;
case 4: return self->BBinCount;
case 5: return self->BBins;
}
}
return MP_OBJ_NULL; // op not supported
}
mp_obj_t py_histogram_bin_count(mp_obj_t self_in) { return ((py_histogram_obj_t *) self_in)->LBinCount; }
mp_obj_t py_histogram_l_bin_count(mp_obj_t self_in) { return ((py_histogram_obj_t *) self_in)->LBinCount; }
mp_obj_t py_histogram_a_bin_count(mp_obj_t self_in) { return ((py_histogram_obj_t *) self_in)->ABinCount; }
mp_obj_t py_histogram_b_bin_count(mp_obj_t self_in) { return ((py_histogram_obj_t *) self_in)->BBinCount; }
mp_obj_t py_histogram_bins(mp_obj_t self_in) { return ((py_histogram_obj_t *) self_in)->LBins; }
mp_obj_t py_histogram_l_bins(mp_obj_t self_in) { return ((py_histogram_obj_t *) self_in)->LBins; }
mp_obj_t py_histogram_a_bins(mp_obj_t self_in) { return ((py_histogram_obj_t *) self_in)->ABins; }
mp_obj_t py_histogram_b_bins(mp_obj_t self_in) { return ((py_histogram_obj_t *) self_in)->BBins; }
mp_obj_t py_histogram_get_percentile(mp_obj_t self_in, mp_obj_t percentile)
{
histogram_t hist;
hist.LBinCount = mp_obj_get_int(((py_histogram_obj_t *) self_in)->LBinCount);
hist.ABinCount = mp_obj_get_int(((py_histogram_obj_t *) self_in)->ABinCount);
hist.BBinCount = mp_obj_get_int(((py_histogram_obj_t *) self_in)->BBinCount);
hist.LBins = fb_alloc(hist.LBinCount * sizeof(float));
hist.ABins = fb_alloc(hist.ABinCount * sizeof(float));
hist.BBins = fb_alloc(hist.BBinCount * sizeof(float));
for (int i = 0; i < hist.LBinCount; i++) {
hist.LBins[i] = mp_obj_get_float(((mp_obj_list_t *) ((py_histogram_obj_t *) self_in)->LBins)->items[i]);
}
for (int i = 0; i < hist.ABinCount; i++) {
hist.ABins[i] = mp_obj_get_float(((mp_obj_list_t *) ((py_histogram_obj_t *) self_in)->ABins)->items[i]);
}
for (int i = 0; i < hist.BBinCount; i++) {
hist.BBins[i] = mp_obj_get_float(((mp_obj_list_t *) ((py_histogram_obj_t *) self_in)->BBins)->items[i]);
}
percentile_t p;
imlib_get_percentile(&p, ((py_histogram_obj_t *) self_in)->type, &hist, mp_obj_get_float(percentile));
if (hist.BBinCount) fb_free();
if (hist.ABinCount) fb_free();
if (hist.LBinCount) fb_free();
py_percentile_obj_t *o = m_new_obj(py_percentile_obj_t);
o->type = ((py_histogram_obj_t *) self_in)->type;
o->LValue = mp_obj_new_int(p.LValue);
o->AValue = mp_obj_new_int(p.AValue);
o->BValue = mp_obj_new_int(p.BValue);
return o;
}
mp_obj_t py_histogram_get_statistics(mp_obj_t self_in)
{
histogram_t hist;
hist.LBinCount = mp_obj_get_int(((py_histogram_obj_t *) self_in)->LBinCount);
hist.ABinCount = mp_obj_get_int(((py_histogram_obj_t *) self_in)->ABinCount);
hist.BBinCount = mp_obj_get_int(((py_histogram_obj_t *) self_in)->BBinCount);
hist.LBins = fb_alloc(hist.LBinCount * sizeof(float));
hist.ABins = fb_alloc(hist.ABinCount * sizeof(float));
hist.BBins = fb_alloc(hist.BBinCount * sizeof(float));
for (int i = 0; i < hist.LBinCount; i++) {
hist.LBins[i] = mp_obj_get_float(((mp_obj_list_t *) ((py_histogram_obj_t *) self_in)->LBins)->items[i]);
}
for (int i = 0; i < hist.ABinCount; i++) {
hist.ABins[i] = mp_obj_get_float(((mp_obj_list_t *) ((py_histogram_obj_t *) self_in)->ABins)->items[i]);
}
for (int i = 0; i < hist.BBinCount; i++) {
hist.BBins[i] = mp_obj_get_float(((mp_obj_list_t *) ((py_histogram_obj_t *) self_in)->BBins)->items[i]);
}
statistics_t stats;
imlib_get_statistics(&stats, ((py_histogram_obj_t *) self_in)->type, &hist);
if (hist.BBinCount) fb_free();
if (hist.ABinCount) fb_free();
if (hist.LBinCount) fb_free();
py_statistics_obj_t *o = m_new_obj(py_statistics_obj_t);
o->type = ((py_histogram_obj_t *) self_in)->type;
o->LMean = mp_obj_new_int(stats.LMean);
o->LMedian = mp_obj_new_int(stats.LMedian);
o->LMode= mp_obj_new_int(stats.LMode);
o->LSTDev = mp_obj_new_int(stats.LSTDev);
o->LMin = mp_obj_new_int(stats.LMin);
o->LMax = mp_obj_new_int(stats.LMax);
o->LLQ = mp_obj_new_int(stats.LLQ);
o->LUQ = mp_obj_new_int(stats.LUQ);
o->AMean = mp_obj_new_int(stats.AMean);
o->AMedian = mp_obj_new_int(stats.AMedian);
o->AMode= mp_obj_new_int(stats.AMode);
o->ASTDev = mp_obj_new_int(stats.ASTDev);
o->AMin = mp_obj_new_int(stats.AMin);
o->AMax = mp_obj_new_int(stats.AMax);
o->ALQ = mp_obj_new_int(stats.ALQ);
o->AUQ = mp_obj_new_int(stats.AUQ);
o->BMean = mp_obj_new_int(stats.BMean);
o->BMedian = mp_obj_new_int(stats.BMedian);
o->BMode= mp_obj_new_int(stats.BMode);
o->BSTDev = mp_obj_new_int(stats.BSTDev);
o->BMin = mp_obj_new_int(stats.BMin);
o->BMax = mp_obj_new_int(stats.BMax);
o->BLQ = mp_obj_new_int(stats.BLQ);
o->BUQ = mp_obj_new_int(stats.BUQ);
return o;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_histogram_bin_count_obj, py_histogram_bin_count);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_histogram_l_bin_count_obj, py_histogram_l_bin_count);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_histogram_a_bin_count_obj, py_histogram_a_bin_count);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_histogram_b_bin_count_obj, py_histogram_b_bin_count);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_histogram_bins_obj, py_histogram_bins);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_histogram_l_bins_obj, py_histogram_l_bins);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_histogram_a_bins_obj, py_histogram_a_bins);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_histogram_b_bins_obj, py_histogram_b_bins);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_histogram_get_percentile_obj, py_histogram_get_percentile);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_histogram_get_statistics_obj, py_histogram_get_statistics);
STATIC const mp_rom_map_elem_t py_histogram_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_bin_count), MP_ROM_PTR(&py_histogram_bin_count_obj) },
{ MP_ROM_QSTR(MP_QSTR_l_bin_count), MP_ROM_PTR(&py_histogram_l_bin_count_obj) },
{ MP_ROM_QSTR(MP_QSTR_a_bin_count), MP_ROM_PTR(&py_histogram_a_bin_count_obj) },
{ MP_ROM_QSTR(MP_QSTR_b_bin_count), MP_ROM_PTR(&py_histogram_b_bin_count_obj) },
{ MP_ROM_QSTR(MP_QSTR_bins), MP_ROM_PTR(&py_histogram_bins_obj) },
{ MP_ROM_QSTR(MP_QSTR_l_bins), MP_ROM_PTR(&py_histogram_l_bins_obj) },
{ MP_ROM_QSTR(MP_QSTR_a_bins), MP_ROM_PTR(&py_histogram_a_bins_obj) },
{ MP_ROM_QSTR(MP_QSTR_b_bins), MP_ROM_PTR(&py_histogram_b_bins_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_percentile), MP_ROM_PTR(&py_histogram_get_percentile_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_stats), MP_ROM_PTR(&py_histogram_get_statistics_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_statistics), MP_ROM_PTR(&py_histogram_get_statistics_obj) },
{ MP_ROM_QSTR(MP_QSTR_statistics), MP_ROM_PTR(&py_histogram_get_statistics_obj) }
};
STATIC MP_DEFINE_CONST_DICT(py_histogram_locals_dict, py_histogram_locals_dict_table);
static const mp_obj_type_t py_histogram_type = {
{ &mp_type_type },
.name = MP_QSTR_histogram,
.print = py_histogram_print,
.subscr = py_histogram_subscr,
.locals_dict = (mp_obj_t) &py_histogram_locals_dict,
};
static void py_percentile_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind)
{
py_percentile_obj_t *self = self_in;
switch(self->type) {
case IMAGE_TYPE_BINARY: {
mp_printf(print, "{value:%d}", mp_obj_get_int(self->LValue));
break;
}
case IMAGE_TYPE_GRAYSCALE: {
mp_printf(print, "{value:%d}", mp_obj_get_int(self->LValue));
break;
}
case IMAGE_TYPE_RGB565: {
mp_printf(print, "{l_value:%d, a_value:%d, b_value:%d}", mp_obj_get_int(self->LValue), mp_obj_get_int(self->AValue), mp_obj_get_int(self->BValue));
break;
}
default: {
mp_printf(print, "{}");
break;
}
}
}
static mp_obj_t py_percentile_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value)
{
if (value == MP_OBJ_SENTINEL) { // load
py_percentile_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_percentile_obj_size, index, &slice)) {
mp_not_implemented("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->LValue) + slice.start, result->len, mp_obj_t);
return result;
}
switch (mp_get_index(self->base.type, py_percentile_obj_size, index, false)) {
case 0: return self->LValue;
case 1: return self->AValue;
case 2: return self->BValue;
}
}
return MP_OBJ_NULL; // op not supported
}
mp_obj_t py_percentile_value(mp_obj_t self_in) { return ((py_percentile_obj_t *) self_in)->LValue; }
mp_obj_t py_percentile_l_value(mp_obj_t self_in) { return ((py_percentile_obj_t *) self_in)->LValue; }
mp_obj_t py_percentile_a_value(mp_obj_t self_in) { return ((py_percentile_obj_t *) self_in)->AValue; }
mp_obj_t py_percentile_b_value(mp_obj_t self_in) { return ((py_percentile_obj_t *) self_in)->BValue; }
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_percentile_value_obj, py_percentile_value);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_percentile_l_value_obj, py_percentile_l_value);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_percentile_a_value_obj, py_percentile_a_value);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_percentile_b_value_obj, py_percentile_b_value);
STATIC const mp_rom_map_elem_t py_percentile_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&py_percentile_value_obj) },
{ MP_ROM_QSTR(MP_QSTR_l_value), MP_ROM_PTR(&py_percentile_l_value_obj) },
{ MP_ROM_QSTR(MP_QSTR_a_value), MP_ROM_PTR(&py_percentile_a_value_obj) },
{ MP_ROM_QSTR(MP_QSTR_b_value), MP_ROM_PTR(&py_percentile_b_value_obj) }
};
STATIC MP_DEFINE_CONST_DICT(py_percentile_locals_dict, py_percentile_locals_dict_table);
static const mp_obj_type_t py_percentile_type = {
{ &mp_type_type },
.name = MP_QSTR_percentile,
.print = py_percentile_print,
.subscr = py_percentile_subscr,
.locals_dict = (mp_obj_t) &py_percentile_locals_dict,
};
static void py_statistics_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind)
{
py_statistics_obj_t *self = self_in;
switch(self->type) {
case IMAGE_TYPE_BINARY: {
mp_printf(print, "{mean:%d, median:%d, mode:%d, stdev:%d, min:%d, max:%d, lq:%d, uq:%d}",
mp_obj_get_int(self->LMean),
mp_obj_get_int(self->LMedian),
mp_obj_get_int(self->LMode),
mp_obj_get_int(self->LSTDev),
mp_obj_get_int(self->LMin),
mp_obj_get_int(self->LMax),
mp_obj_get_int(self->LLQ),
mp_obj_get_int(self->LUQ));
break;
}
case IMAGE_TYPE_GRAYSCALE: {
mp_printf(print, "{mean:%d, median:%d, mode:%d, stdev:%d, min:%d, max:%d, lq:%d, uq:%d}",
mp_obj_get_int(self->LMean),
mp_obj_get_int(self->LMedian),
mp_obj_get_int(self->LMode),
mp_obj_get_int(self->LSTDev),
mp_obj_get_int(self->LMin),
mp_obj_get_int(self->LMax),
mp_obj_get_int(self->LLQ),
mp_obj_get_int(self->LUQ));
break;
}
case IMAGE_TYPE_RGB565: {
mp_printf(print, "{l_mean:%d, l_median:%d, l_mode:%d, l_stdev:%d, l_min:%d, l_max:%d, l_lq:%d, l_uq:%d,"
" a_mean:%d, a_median:%d, a_mode:%d, a_stdev:%d, a_min:%d, a_max:%d, a_lq:%d, a_uq:%d,"
" b_mean:%d, b_median:%d, b_mode:%d, b_stdev:%d, b_min:%d, b_max:%d, b_lq:%d, b_uq:%d}",
mp_obj_get_int(self->LMean),
mp_obj_get_int(self->LMedian),
mp_obj_get_int(self->LMode),
mp_obj_get_int(self->LSTDev),
mp_obj_get_int(self->LMin),
mp_obj_get_int(self->LMax),
mp_obj_get_int(self->LLQ),
mp_obj_get_int(self->LUQ),
mp_obj_get_int(self->AMean),
mp_obj_get_int(self->AMedian),
mp_obj_get_int(self->AMode),
mp_obj_get_int(self->ASTDev),
mp_obj_get_int(self->AMin),
mp_obj_get_int(self->AMax),
mp_obj_get_int(self->ALQ),
mp_obj_get_int(self->AUQ),
mp_obj_get_int(self->BMean),
mp_obj_get_int(self->BMedian),
mp_obj_get_int(self->BMode),
mp_obj_get_int(self->BSTDev),
mp_obj_get_int(self->BMin),
mp_obj_get_int(self->BMax),
mp_obj_get_int(self->BLQ),
mp_obj_get_int(self->BUQ));
break;
}
default: {
mp_printf(print, "{}");
break;
}
}
}
static mp_obj_t py_statistics_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value)
{
if (value == MP_OBJ_SENTINEL) { // load
py_statistics_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_statistics_obj_size, index, &slice)) {
mp_not_implemented("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->LMean) + slice.start, result->len, mp_obj_t);
return result;
}
switch (mp_get_index(self->base.type, py_statistics_obj_size, index, false)) {
case 0: return self->LMean;
case 1: return self->LMedian;
case 2: return self->LMode;
case 3: return self->LSTDev;
case 4: return self->LMin;
case 5: return self->LMax;
case 6: return self->LLQ;
case 7: return self->LUQ;
case 8: return self->AMean;
case 9: return self->AMedian;
case 10: return self->AMode;
case 11: return self->ASTDev;
case 12: return self->AMin;
case 13: return self->AMax;
case 14: return self->ALQ;
case 15: return self->AUQ;
case 16: return self->BMean;
case 17: return self->BMedian;
case 18: return self->BMode;
case 19: return self->BSTDev;
case 20: return self->BMin;
case 21: return self->BMax;
case 22: return self->BLQ;
case 23: return self->BUQ;
}
}
return MP_OBJ_NULL; // op not supported
}
mp_obj_t py_statistics_mean(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->LMean; }
mp_obj_t py_statistics_median(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->LMedian; }
mp_obj_t py_statistics_mode(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->LMode; }
mp_obj_t py_statistics_stdev(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->LSTDev; }
mp_obj_t py_statistics_min(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->LMin; }
mp_obj_t py_statistics_max(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->LMax; }
mp_obj_t py_statistics_lq(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->LLQ; }
mp_obj_t py_statistics_uq(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->LUQ; }
mp_obj_t py_statistics_l_mean(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->LMean; }
mp_obj_t py_statistics_l_median(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->LMedian; }
mp_obj_t py_statistics_l_mode(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->LMode; }
mp_obj_t py_statistics_l_stdev(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->LSTDev; }
mp_obj_t py_statistics_l_min(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->LMin; }
mp_obj_t py_statistics_l_max(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->LMax; }
mp_obj_t py_statistics_l_lq(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->LLQ; }
mp_obj_t py_statistics_l_uq(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->LUQ; }
mp_obj_t py_statistics_a_mean(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->AMean; }
mp_obj_t py_statistics_a_median(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->AMedian; }
mp_obj_t py_statistics_a_mode(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->AMode; }
mp_obj_t py_statistics_a_stdev(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->ASTDev; }
mp_obj_t py_statistics_a_min(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->AMin; }
mp_obj_t py_statistics_a_max(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->AMax; }
mp_obj_t py_statistics_a_lq(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->ALQ; }
mp_obj_t py_statistics_a_uq(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->AUQ; }
mp_obj_t py_statistics_b_mean(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->BMean; }
mp_obj_t py_statistics_b_median(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->BMedian; }
mp_obj_t py_statistics_b_mode(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->BMode; }
mp_obj_t py_statistics_b_stdev(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->BSTDev; }
mp_obj_t py_statistics_b_min(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->BMin; }
mp_obj_t py_statistics_b_max(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->BMax; }
mp_obj_t py_statistics_b_lq(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->BLQ; }
mp_obj_t py_statistics_b_uq(mp_obj_t self_in) { return ((py_statistics_obj_t *) self_in)->BUQ; }
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_mean_obj, py_statistics_mean);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_median_obj, py_statistics_median);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_mode_obj, py_statistics_mode);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_stdev_obj, py_statistics_stdev);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_min_obj, py_statistics_min);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_max_obj, py_statistics_max);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_lq_obj, py_statistics_lq);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_uq_obj, py_statistics_uq);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_l_mean_obj, py_statistics_l_mean);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_l_median_obj, py_statistics_l_median);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_l_mode_obj, py_statistics_l_mode);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_l_stdev_obj, py_statistics_l_stdev);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_l_min_obj, py_statistics_l_min);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_l_max_obj, py_statistics_l_max);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_l_lq_obj, py_statistics_l_lq);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_l_uq_obj, py_statistics_l_uq);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_a_mean_obj, py_statistics_a_mean);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_a_median_obj, py_statistics_a_median);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_a_mode_obj, py_statistics_a_mode);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_a_stdev_obj, py_statistics_a_stdev);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_a_min_obj, py_statistics_a_min);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_a_max_obj, py_statistics_a_max);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_a_lq_obj, py_statistics_a_lq);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_a_uq_obj, py_statistics_a_uq);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_b_mean_obj, py_statistics_b_mean);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_b_median_obj, py_statistics_b_median);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_b_mode_obj, py_statistics_b_mode);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_b_stdev_obj, py_statistics_b_stdev);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_b_min_obj, py_statistics_b_min);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_b_max_obj, py_statistics_b_max);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_b_lq_obj, py_statistics_b_lq);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_statistics_b_uq_obj, py_statistics_b_uq);
STATIC const mp_rom_map_elem_t py_statistics_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_mean), MP_ROM_PTR(&py_statistics_mean_obj) },
{ MP_ROM_QSTR(MP_QSTR_median), MP_ROM_PTR(&py_statistics_median_obj) },
{ MP_ROM_QSTR(MP_QSTR_mode), MP_ROM_PTR(&py_statistics_mode_obj) },
{ MP_ROM_QSTR(MP_QSTR_stdev), MP_ROM_PTR(&py_statistics_stdev_obj) },
{ MP_ROM_QSTR(MP_QSTR_min), MP_ROM_PTR(&py_statistics_min_obj) },
{ MP_ROM_QSTR(MP_QSTR_max), MP_ROM_PTR(&py_statistics_max_obj) },
{ MP_ROM_QSTR(MP_QSTR_lq), MP_ROM_PTR(&py_statistics_lq_obj) },
{ MP_ROM_QSTR(MP_QSTR_uq), MP_ROM_PTR(&py_statistics_uq_obj) },
{ MP_ROM_QSTR(MP_QSTR_l_mean), MP_ROM_PTR(&py_statistics_l_mean_obj) },
{ MP_ROM_QSTR(MP_QSTR_l_median), MP_ROM_PTR(&py_statistics_l_median_obj) },
{ MP_ROM_QSTR(MP_QSTR_l_mode), MP_ROM_PTR(&py_statistics_l_mode_obj) },
{ MP_ROM_QSTR(MP_QSTR_l_stdev), MP_ROM_PTR(&py_statistics_l_stdev_obj) },
{ MP_ROM_QSTR(MP_QSTR_l_min), MP_ROM_PTR(&py_statistics_l_min_obj) },
{ MP_ROM_QSTR(MP_QSTR_l_max), MP_ROM_PTR(&py_statistics_l_max_obj) },
{ MP_ROM_QSTR(MP_QSTR_l_lq), MP_ROM_PTR(&py_statistics_l_lq_obj) },
{ MP_ROM_QSTR(MP_QSTR_l_uq), MP_ROM_PTR(&py_statistics_l_uq_obj) },
{ MP_ROM_QSTR(MP_QSTR_a_mean), MP_ROM_PTR(&py_statistics_a_mean_obj) },
{ MP_ROM_QSTR(MP_QSTR_a_median), MP_ROM_PTR(&py_statistics_a_median_obj) },
{ MP_ROM_QSTR(MP_QSTR_a_mode), MP_ROM_PTR(&py_statistics_a_mode_obj) },
{ MP_ROM_QSTR(MP_QSTR_a_stdev), MP_ROM_PTR(&py_statistics_a_stdev_obj) },
{ MP_ROM_QSTR(MP_QSTR_a_min), MP_ROM_PTR(&py_statistics_a_min_obj) },
{ MP_ROM_QSTR(MP_QSTR_a_max), MP_ROM_PTR(&py_statistics_a_max_obj) },
{ MP_ROM_QSTR(MP_QSTR_a_lq), MP_ROM_PTR(&py_statistics_a_lq_obj) },
{ MP_ROM_QSTR(MP_QSTR_a_uq), MP_ROM_PTR(&py_statistics_a_uq_obj) },
{ MP_ROM_QSTR(MP_QSTR_b_mean), MP_ROM_PTR(&py_statistics_b_mean_obj) },
{ MP_ROM_QSTR(MP_QSTR_b_median), MP_ROM_PTR(&py_statistics_b_median_obj) },
{ MP_ROM_QSTR(MP_QSTR_b_mode), MP_ROM_PTR(&py_statistics_b_mode_obj) },
{ MP_ROM_QSTR(MP_QSTR_b_stdev), MP_ROM_PTR(&py_statistics_b_stdev_obj) },
{ MP_ROM_QSTR(MP_QSTR_b_min), MP_ROM_PTR(&py_statistics_b_min_obj) },
{ MP_ROM_QSTR(MP_QSTR_b_max), MP_ROM_PTR(&py_statistics_b_max_obj) },
{ MP_ROM_QSTR(MP_QSTR_b_lq), MP_ROM_PTR(&py_statistics_b_lq_obj) },
{ MP_ROM_QSTR(MP_QSTR_b_uq), MP_ROM_PTR(&py_statistics_b_uq_obj) }
};
STATIC MP_DEFINE_CONST_DICT(py_statistics_locals_dict, py_statistics_locals_dict_table);
static const mp_obj_type_t py_statistics_type = {
{ &mp_type_type },
.name = MP_QSTR_statistics,
.print = py_statistics_print,
.subscr = py_statistics_subscr,
.locals_dict = (mp_obj_t) &py_statistics_locals_dict,
};
static mp_obj_t py_image_get_histogram(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
image_t *arg_img = py_image_cobj(args[0]);
PY_ASSERT_FALSE_MSG(IM_IS_JPEG(arg_img),
"Operation not supported on JPEG");
// Transfer to new image type.
new_image_t image;
image_init(&image, (arg_img->bpp == 2) ? IMAGE_TYPE_RGB565 : IMAGE_TYPE_GRAYSCALE, arg_img->w, arg_img->h);
image.size = arg_img->bpp * arg_img->w * arg_img->h;
image.data = arg_img->pixels;
rectangle_t roi;
py_helper_lookup_rectangle(kw_args, arg_img, &roi);
// TODO: Need to set fb_alloc trap here to recover from any exception...
histogram_t hist;
switch(image.type) {
case IMAGE_TYPE_BINARY: {
int bin_count = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_bin_count), (COLOR_BINARY_MAX-COLOR_BINARY_MIN+1));
PY_ASSERT_TRUE_MSG(bin_count >= 2, "bin_count must be >= 2");
hist.LBinCount = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_l_bin_count), bin_count);
PY_ASSERT_TRUE_MSG(hist.LBinCount >= 2, "l_bin_count must be >= 2");
hist.ABinCount = 0;
hist.BBinCount = 0;
hist.LBins = fb_alloc(hist.LBinCount * sizeof(float));
hist.ABins = NULL;
hist.BBins = NULL;
imlib_get_histogram(&hist, &image, &roi);
break;
}
case IMAGE_TYPE_GRAYSCALE: {
int bin_count = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_bin_count), (COLOR_GRAYSCALE_MAX-COLOR_GRAYSCALE_MIN+1));
PY_ASSERT_TRUE_MSG(bin_count >= 2, "bin_count must be >= 2");
hist.LBinCount = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_l_bin_count), bin_count);
PY_ASSERT_TRUE_MSG(hist.LBinCount >= 2, "l_bin_count must be >= 2");
hist.ABinCount = 0;
hist.BBinCount = 0;
hist.LBins = fb_alloc(hist.LBinCount * sizeof(float));
hist.ABins = NULL;
hist.BBins = NULL;
imlib_get_histogram(&hist, &image, &roi);
break;
}
case IMAGE_TYPE_RGB565: {
int l_bin_count = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_bin_count), (COLOR_L_MAX-COLOR_L_MIN+1));
PY_ASSERT_TRUE_MSG(l_bin_count >= 2, "bin_count must be >= 2");
hist.LBinCount = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_l_bin_count), l_bin_count);
PY_ASSERT_TRUE_MSG(hist.LBinCount >= 2, "l_bin_count must be >= 2");
int a_bin_count = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_bin_count), (COLOR_A_MAX-COLOR_A_MIN+1));
PY_ASSERT_TRUE_MSG(a_bin_count >= 2, "bin_count must be >= 2");
hist.ABinCount = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_a_bin_count), a_bin_count);
PY_ASSERT_TRUE_MSG(hist.ABinCount >= 2, "a_bin_count must be >= 2");
int b_bin_count = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_bin_count), (COLOR_B_MAX-COLOR_B_MIN+1));
PY_ASSERT_TRUE_MSG(b_bin_count >= 2, "bin_count must be >= 2");
hist.BBinCount = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_b_bin_count), b_bin_count);
PY_ASSERT_TRUE_MSG(hist.BBinCount >= 2, "b_bin_count must be >= 2");
hist.LBins = fb_alloc(hist.LBinCount * sizeof(float));
hist.ABins = fb_alloc(hist.ABinCount * sizeof(float));
hist.BBins = fb_alloc(hist.BBinCount * sizeof(float));
imlib_get_histogram(&hist, &image, &roi);
break;
}
default: {
return MP_OBJ_NULL;
}
}
py_histogram_obj_t *o = m_new_obj(py_histogram_obj_t);
o->type = image.type;
o->LBinCount = mp_obj_new_int(hist.LBinCount);
o->LBins = hist.LBinCount ? mp_obj_new_list(hist.LBinCount, NULL) : MP_OBJ_NULL;
for (int i = 0; i < hist.LBinCount; i++) {
((mp_obj_list_t *) o->LBins)->items[i] = mp_obj_new_float(hist.LBins[i]);
}
o->ABinCount = mp_obj_new_int(hist.ABinCount);
o->ABins = hist.ABinCount ? mp_obj_new_list(hist.ABinCount, NULL) : MP_OBJ_NULL;
for (int i = 0; i < hist.ABinCount; i++) {
((mp_obj_list_t *) o->ABins)->items[i] = mp_obj_new_float(hist.ABins[i]);
}
o->BBinCount = mp_obj_new_int(hist.BBinCount);
o->BBins = hist.BBinCount ? mp_obj_new_list(hist.BBinCount, NULL) : MP_OBJ_NULL;
for (int i = 0; i < hist.BBinCount; i++) {
((mp_obj_list_t *) o->BBins)->items[i] = mp_obj_new_float(hist.BBins[i]);
}
if (hist.BBinCount) fb_free();
if (hist.ABinCount) fb_free();
if (hist.LBinCount) fb_free();
return o;
}
static mp_obj_t py_image_get_statistics(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
image_t *arg_img = py_image_cobj(args[0]);
PY_ASSERT_FALSE_MSG(IM_IS_JPEG(arg_img),
"Operation not supported on JPEG");
// Transfer to new image type.
new_image_t image;
image_init(&image, (arg_img->bpp == 2) ? IMAGE_TYPE_RGB565 : IMAGE_TYPE_GRAYSCALE, arg_img->w, arg_img->h);
image.size = arg_img->bpp * arg_img->w * arg_img->h;
image.data = arg_img->pixels;
rectangle_t roi;
py_helper_lookup_rectangle(kw_args, arg_img, &roi);
// TODO: Need to set fb_alloc trap here to recover from any exception...
histogram_t hist;
switch(image.type) {
case IMAGE_TYPE_BINARY: {
int bin_count = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_bin_count), (COLOR_BINARY_MAX-COLOR_BINARY_MIN+1));
PY_ASSERT_TRUE_MSG(bin_count >= 2, "bin_count must be >= 2");
hist.LBinCount = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_l_bin_count), bin_count);
PY_ASSERT_TRUE_MSG(hist.LBinCount >= 2, "l_bin_count must be >= 2");
hist.ABinCount = 0;
hist.BBinCount = 0;
hist.LBins = fb_alloc(hist.LBinCount * sizeof(float));
hist.ABins = NULL;
hist.BBins = NULL;
imlib_get_histogram(&hist, &image, &roi);
break;
}
case IMAGE_TYPE_GRAYSCALE: {
int bin_count = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_bin_count), (COLOR_GRAYSCALE_MAX-COLOR_GRAYSCALE_MIN+1));
PY_ASSERT_TRUE_MSG(bin_count >= 2, "bin_count must be >= 2");
hist.LBinCount = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_l_bin_count), bin_count);
PY_ASSERT_TRUE_MSG(hist.LBinCount >= 2, "l_bin_count must be >= 2");
hist.ABinCount = 0;
hist.BBinCount = 0;
hist.LBins = fb_alloc(hist.LBinCount * sizeof(float));
hist.ABins = NULL;
hist.BBins = NULL;
imlib_get_histogram(&hist, &image, &roi);
break;
}
case IMAGE_TYPE_RGB565: {
int l_bin_count = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_bin_count), (COLOR_L_MAX-COLOR_L_MIN+1));
PY_ASSERT_TRUE_MSG(l_bin_count >= 2, "bin_count must be >= 2");
hist.LBinCount = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_l_bin_count), l_bin_count);
PY_ASSERT_TRUE_MSG(hist.LBinCount >= 2, "l_bin_count must be >= 2");
int a_bin_count = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_bin_count), (COLOR_A_MAX-COLOR_A_MIN+1));
PY_ASSERT_TRUE_MSG(a_bin_count >= 2, "bin_count must be >= 2");
hist.ABinCount = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_a_bin_count), a_bin_count);
PY_ASSERT_TRUE_MSG(hist.ABinCount >= 2, "a_bin_count must be >= 2");
int b_bin_count = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_bin_count), (COLOR_B_MAX-COLOR_B_MIN+1));
PY_ASSERT_TRUE_MSG(b_bin_count >= 2, "bin_count must be >= 2");
hist.BBinCount = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_b_bin_count), b_bin_count);
PY_ASSERT_TRUE_MSG(hist.BBinCount >= 2, "b_bin_count must be >= 2");
hist.LBins = fb_alloc(hist.LBinCount * sizeof(float));
hist.ABins = fb_alloc(hist.ABinCount * sizeof(float));
hist.BBins = fb_alloc(hist.BBinCount * sizeof(float));
imlib_get_histogram(&hist, &image, &roi);
break;
}
default: {
return MP_OBJ_NULL;
}
}
statistics_t stats;
imlib_get_statistics(&stats, image.type, &hist);
if (hist.BBinCount) fb_free();
if (hist.ABinCount) fb_free();
if (hist.LBinCount) fb_free();
py_statistics_obj_t *o = m_new_obj(py_statistics_obj_t);
o->type = image.type;
o->LMean = mp_obj_new_int(stats.LMean);
o->LMedian = mp_obj_new_int(stats.LMedian);
o->LMode= mp_obj_new_int(stats.LMode);
o->LSTDev = mp_obj_new_int(stats.LSTDev);
o->LMin = mp_obj_new_int(stats.LMin);
o->LMax = mp_obj_new_int(stats.LMax);
o->LLQ = mp_obj_new_int(stats.LLQ);
o->LUQ = mp_obj_new_int(stats.LUQ);
o->AMean = mp_obj_new_int(stats.AMean);
o->AMedian = mp_obj_new_int(stats.AMedian);
o->AMode= mp_obj_new_int(stats.AMode);
o->ASTDev = mp_obj_new_int(stats.ASTDev);
o->AMin = mp_obj_new_int(stats.AMin);
o->AMax = mp_obj_new_int(stats.AMax);
o->ALQ = mp_obj_new_int(stats.ALQ);
o->AUQ = mp_obj_new_int(stats.AUQ);
o->BMean = mp_obj_new_int(stats.BMean);
o->BMedian = mp_obj_new_int(stats.BMedian);
o->BMode= mp_obj_new_int(stats.BMode);
o->BSTDev = mp_obj_new_int(stats.BSTDev);
o->BMin = mp_obj_new_int(stats.BMin);
o->BMax = mp_obj_new_int(stats.BMax);
o->BLQ = mp_obj_new_int(stats.BLQ);
o->BUQ = mp_obj_new_int(stats.BUQ);
return o;
}
// Blob Object //
#define py_blob_obj_size 10
typedef struct py_blob_obj {
@ -1678,8 +2359,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_replace_obj, py_image_replace);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_blend_obj, 2, py_image_blend);
/* Image Morphing */
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_morph_obj, 3, py_image_morph);
/* Image Statistics */
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_statistics_obj, 1, py_image_statistics);
/* Image Filtering */
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_midpoint_obj, 2, py_image_midpoint);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_mean_obj, py_image_mean);
@ -1689,6 +2368,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_gaussian_obj, 1, py_image_gaussian);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_histeq_obj, py_image_histeq);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_lens_corr_obj, py_image_lens_corr);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_mask_ellipse_obj, py_image_mask_ellipse);
/* Image Statistics */
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);
/* Color Tracking */
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_find_blobs_obj, 2, py_image_find_blobs);
/* Code Detection */
@ -1748,8 +2430,6 @@ static const mp_map_elem_t locals_dict_table[] = {
{MP_OBJ_NEW_QSTR(MP_QSTR_blend), (mp_obj_t)&py_image_blend_obj},
/* Image Morphing */
{MP_OBJ_NEW_QSTR(MP_QSTR_morph), (mp_obj_t)&py_image_morph_obj},
/* Image Statistics */
{MP_OBJ_NEW_QSTR(MP_QSTR_statistics), (mp_obj_t)&py_image_statistics_obj},
/* Image Filtering */
{MP_OBJ_NEW_QSTR(MP_QSTR_midpoint), (mp_obj_t)&py_image_midpoint_obj},
{MP_OBJ_NEW_QSTR(MP_QSTR_mean), (mp_obj_t)&py_image_mean_obj},
@ -1759,6 +2439,13 @@ static const mp_map_elem_t locals_dict_table[] = {
{MP_OBJ_NEW_QSTR(MP_QSTR_histeq), (mp_obj_t)&py_image_histeq_obj},
{MP_OBJ_NEW_QSTR(MP_QSTR_lens_corr), (mp_obj_t)&py_image_lens_corr_obj},
{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_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},
{MP_OBJ_NEW_QSTR(MP_QSTR_get_stats), (mp_obj_t)&py_image_get_statistics_obj},
{MP_OBJ_NEW_QSTR(MP_QSTR_get_statistics), (mp_obj_t)&py_image_get_statistics_obj},
{MP_OBJ_NEW_QSTR(MP_QSTR_statistics), (mp_obj_t)&py_image_get_statistics_obj},
/* Color Tracking */
{MP_OBJ_NEW_QSTR(MP_QSTR_find_blobs), (mp_obj_t)&py_image_find_blobs_obj},
/* Code Detection */

View File

@ -59,7 +59,6 @@ Q(difference)
Q(replace)
Q(blend)
Q(morph)
Q(statistics)
Q(midpoint)
Q(mean)
Q(mode)
@ -307,6 +306,68 @@ Q(CPUFREQ_216MHZ)
Q(get_frequency)
Q(set_frequency)
// Get Histogram
Q(get_hist)
Q(get_histogram)
// Histogram Object
Q(histogram)
Q(bin_count)
Q(l_bin_count)
Q(a_bin_count)
Q(b_bin_count)
Q(bins)
Q(l_bins)
Q(a_bins)
Q(b_bins)
Q(get_percentile)
Q(get_stats)
Q(get_statistics)
Q(statistics)
// Percentile Object
// duplicate Q(percentile)
Q(value)
Q(l_value)
Q(a_value)
Q(b_value)
// Get Statistics
// duplicate Q(get_stats)
// duplicate Q(get_statistics)
// Statistics Object
// duplicate Q(statistics)
// duplicate Q(mean)
// duplicate Q(median)
// duplicate Q(mode)
Q(stdev)
// duplicate Q(min)
// duplicate Q(max)
Q(lq)
Q(uq)
Q(l_mean)
Q(l_median)
Q(l_mode)
Q(l_stdev)
Q(l_min)
Q(l_max)
Q(l_lq)
Q(l_uq)
Q(a_mean)
Q(a_median)
Q(a_mode)
Q(a_stdev)
Q(a_min)
Q(a_max)
Q(a_lq)
Q(a_uq)
Q(b_mean)
Q(b_median)
Q(b_mode)
Q(b_stdev)
Q(b_min)
Q(b_max)
Q(b_lq)
Q(b_uq)
// Find Blobs
Q(find_blobs)
Q(area_threshold)