mirror of
https://github.com/openmv/openmv.git
synced 2025-09-26 23:09:13 +08:00

Originally meant to abstract gc_collect but we could just use m_alloc and friends. Also was meant to provide functions like alloc0, alloc_maybe etc.. which are all available in MP anyway. Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
151 lines
5.3 KiB
C
151 lines
5.3 KiB
C
/*
|
|
* SPDX-License-Identifier: MIT
|
|
*
|
|
* Copyright (C) 2013-2024 OpenMV, LLC.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
*
|
|
* HoG.
|
|
* See Histograms of Oriented Gradients (Navneet Dalal and Bill Triggs)
|
|
*/
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
#include <string.h>
|
|
#include "imlib.h"
|
|
#include "fb_alloc.h"
|
|
|
|
#ifdef IMLIB_ENABLE_HOG
|
|
#define N_BINS (9)
|
|
typedef struct bin {
|
|
int d;
|
|
int m;
|
|
} bin_t;
|
|
|
|
int bin_array_comp(const void *obj0, const void *obj1) {
|
|
const bin_t *b0 = obj0;
|
|
const bin_t *b1 = obj1;
|
|
if (b0->m < b1->m) {
|
|
return -1;
|
|
}
|
|
if (b0->m > b1->m) {
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void imlib_find_hog(image_t *src, rectangle_t *roi, int cell_size) {
|
|
int s = src->w;
|
|
int w = roi->x + roi->w - 1;
|
|
int h = roi->y + roi->h - 1;
|
|
|
|
int block_size = cell_size * 2;
|
|
int x_cells = (roi->w / cell_size);
|
|
int y_cells = (roi->h / cell_size);
|
|
|
|
// TODO: Assert row->w/h >= cell_size *2;
|
|
float *hog = fb_alloc0(x_cells * y_cells * N_BINS * sizeof *hog, FB_ALLOC_NO_HINT);
|
|
|
|
//2. Finding Image Gradients
|
|
for (int y = roi->y, hog_index = 0; y < h; y += block_size) {
|
|
for (int x = roi->x; x < w; x += block_size) {
|
|
float k = 0.0f;
|
|
for (int cy = 0; cy < block_size; cy++) {
|
|
for (int cx = 0; cx < block_size; cx++) {
|
|
if ((y + cy) > 0 && (y + cy) < h && (x + cx) > 0 && (x + cx) < w) {
|
|
// Find horizontal/vertical direction
|
|
int vx = src->data[(y + cy + 0) * s + (x + cx + 1)] - src->data[(y + cy - 0) * s + (x + cx - 1)];
|
|
int vy = src->data[(y + cy + 1) * s + (x + cx + 0)] - src->data[(y + cy - 1) * s + (x + cx - 0)];
|
|
// Find magnitude
|
|
float m = fast_sqrtf(vx * vx + vy * vy);
|
|
if (((int) m) > 1) {
|
|
k += m * m;
|
|
// Find and quantize gradient degree
|
|
// TODO atan2f is swapped for visualization
|
|
int t = ((int) fast_fabsf((atan2f(vx, vy) * 180.0f / M_PI))) / 20;
|
|
t = (t == 9)? 0 : t;
|
|
|
|
// hog[((cy/cell_size) * x_cells + (cx/cell_size)) * N_BINS + t] += m;
|
|
hog[hog_index + (((cy / 8) * 2 + (cx / 8)) * N_BINS) + t] += m;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Normalize the last block
|
|
k = sqrtf(k);
|
|
for (int i = hog_index; i < (hog_index + (N_BINS * 4)); i++) {
|
|
hog[i] = hog[i] / k;
|
|
}
|
|
|
|
hog_index += (N_BINS * 4);
|
|
}
|
|
}
|
|
|
|
memset(src->pixels, 0, src->w * src->h);
|
|
|
|
array_t *gds;
|
|
bin_t bins[9];
|
|
array_alloc(&gds, NULL);
|
|
|
|
for (int i = 0; i < N_BINS; i++) {
|
|
array_push_back(gds, &bins[i]);
|
|
}
|
|
|
|
int l = cell_size / 2;
|
|
// Note cells are not ordered histograms of 4 cells
|
|
for (int by = 0, hog_index = 0; by < y_cells; by += 2) {
|
|
for (int bx = 0; bx < x_cells; bx += 2) {
|
|
for (int y = 0; y < 2; y++) {
|
|
for (int x = 0; x < 2; x++) {
|
|
// Sort and draw bins
|
|
for (int i = hog_index; i < hog_index + N_BINS; i++) {
|
|
int m = (int) (hog[i] * 255);
|
|
if (m > 255) {
|
|
m = 255;
|
|
} else if (m < 0) {
|
|
m = 0;
|
|
}
|
|
bin_t *bin = array_at(gds, (i % N_BINS));
|
|
bin->m = m;
|
|
bin->d = ((i % N_BINS) * 20);
|
|
}
|
|
|
|
array_sort(gds, bin_array_comp);
|
|
|
|
int x1 = (x + bx) * cell_size + l;
|
|
int y1 = (y + by) * cell_size + l;
|
|
for (int i = 0; i < N_BINS; i++) {
|
|
bin_t *bin = array_at(gds, i);
|
|
int x2 = l * cos_table[bin->d];
|
|
int y2 = l * sin_table[bin->d];
|
|
imlib_draw_line(src, (x1 - x2), (y1 + y2), (x1 + x2), (y1 - y2), bin->m, 1);
|
|
}
|
|
|
|
hog_index += N_BINS;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_free(gds);
|
|
fb_free();
|
|
}
|
|
#endif // IMLIB_ENABLE_HOG
|