use constant macros where possible
[sparrow.git] / test-find-edge.c
blob976f289c88528f190a9a263f102a9fa28add7131
1 #include "sparrow.h"
2 #include <string.h>
3 #include <math.h>
4 #include <sys/time.h>
6 #include <stdio.h>
8 #include "cv.h"
9 #include "highgui.h"
11 #define debug(format, ...) fprintf (stderr, (format),## __VA_ARGS__); fflush(stderr)
12 #define debug_lineno() debug("%-25s line %4d \n", __func__, __LINE__ )
15 #define IMG_IN_NAME "images/test-image.png"
16 #define IMG_OUT_NAME "images/test-image-%s.png"
19 static inline void
20 expand_one_mono(int x, int y, int c,
21 CvPoint *nexts, int *n_nexts, guint8 *im, guint8 *mask, int w, int h){
22 guint8 p = im[y * w + x];
23 guint8 *m = &mask[y * w + x];
24 if (*m && (p == c)){
25 *m = 0;
26 nexts[*n_nexts].x = x;
27 nexts[*n_nexts].y = y;
28 (*n_nexts)++;
32 static IplImage*
33 floodfill_mono_superfast(IplImage *im, IplImage *mim, CvPoint start)
35 guint8 * data = (guint8 *)im->imageData;
36 guint8 * mdata = (guint8 *)mim->imageData;
37 int w = im->width;
38 int h = im->height;
39 int n_starts;
40 int n_nexts = 0;
41 CvPoint *starts;
42 CvPoint *nexts;
44 //malloc 2 lists of points. These *could* be as large as the image (but never should be)
45 void * mem = malloc(w * h * 2 * sizeof(CvPoint));
46 starts = mem;
47 nexts = starts + w * h;
49 n_starts = 1;
50 starts[0] = start;
52 while(n_starts){
53 n_nexts = 0;
54 int i;
55 for (i = 0; i < n_starts; i++){
56 int x = starts[i].x;
57 int y = starts[i].y;
58 int c = data[y * w + x];
59 if (x > 0){
60 expand_one_mono(x - 1, y, c, nexts, &n_nexts, data, mdata, w, h);
62 if (x < w - 1){
63 expand_one_mono(x + 1, y, c, nexts, &n_nexts, data, mdata, w, h);
65 if (y > 0){
66 expand_one_mono(x, y - 1, c, nexts, &n_nexts, data, mdata, w, h);
68 if (y < h - 1){
69 expand_one_mono(x, y + 1, c, nexts, &n_nexts, data, mdata, w, h);
72 CvPoint *tmp = starts;
73 starts = nexts;
74 nexts = tmp;
75 n_starts = n_nexts;
77 free(mem);
78 return im;
83 static UNUSED IplImage*
84 test_find_edges_hist(IplImage *im)
86 int w = im->width;
87 int h = im->height;
88 CvSize small_size = {w / 8, h / 8};
89 CvPoint middle = {w/2, h/2};
91 IplImage *small = cvCreateImage(small_size, IPL_DEPTH_8U, 1); /*for quicker histogram */
92 IplImage *mask = cvCreateImage(cvGetSize(im), IPL_DEPTH_8U, 1);
93 IplImage *green = cvCreateImage(cvGetSize(im), IPL_DEPTH_8U, 1);
94 cvSplit(im, NULL, green, NULL, NULL);
96 cvResize(green, small, CV_INTER_NN);
97 //small = green;
99 int hist_size[] = {255};
100 float range[] = {0, 255};
101 float *ranges[] = {range};
102 CvHistogram* hist = cvCreateHist(1, hist_size, CV_HIST_ARRAY, ranges, 1);
103 cvCalcHist(&small, hist, 0, NULL);
105 int pixels = small->width * small->height;
106 int min_black = pixels / 8;
107 int max_black = pixels / 2;
108 int totals[256] = {0};
110 int best_d = pixels + 1;
111 int best_t = 0;
113 int total = 0;
114 for (int i = 0; i < 255; i++){
115 int v = (int)cvQueryHistValue_1D(hist, i + 2);
116 total += v;
117 totals[i] = total;
118 if (total > min_black){
119 if (i > 5){
120 int diff = totals[i] - totals[i - 5];
121 if (diff < best_d){
122 best_d = diff;
123 best_t = i;
125 if (total >= max_black){
126 break;
131 best_t -= 2;
132 printf("found best threshold %d -- %d pixel change at %d/%d pixels\n",
133 best_t, best_d, totals[best_t], pixels);
135 cvCmpS(green, best_t, mask, CV_CMP_GT);
136 IplImage *mask2 = cvCreateImage(cvGetSize(im), IPL_DEPTH_8U, 1);
137 memset(mask2->imageData, 255, w*h);
138 floodfill_mono_superfast(mask, mask2, middle);
139 return mask2;
144 int main(int argc, char **argv)
146 struct timeval tv1, tv2;
147 guint32 t;
149 IplImage *im_in = cvLoadImage(IMG_IN_NAME, CV_LOAD_IMAGE_UNCHANGED);
150 //IplImage *im_out = cvCreateImage(CvSize size, int depth, int channels);
151 //IplImage *im_out = cvCloneImage(im);
153 gettimeofday(&tv1, NULL);
156 IplImage *im_out = test_find_edges_hist(im_in);
157 //IplImage *im_out = test_find_edges(im_in);
160 gettimeofday(&tv2, NULL);
161 t = ((tv2.tv_sec - tv1.tv_sec) * 1000000 +
162 tv2.tv_usec - tv1.tv_usec);
163 printf("took %u microseconds (%0.5f of a frame)\n",
164 t, (double)t * (25.0 / 1000000.0));
167 char *filename;
168 if(asprintf(&filename, IMG_OUT_NAME, "final") == -1){};
169 cvSaveImage(filename, im_out, 0);
170 return EXIT_SUCCESS;