Sumio Morioka / Mbed 2 deprecated if201411_section10

Dependencies:   TextLCD mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002  * Copyright (c) 2014, Sumio Morioka
00003  * All rights reserved.
00004  *
00005  * This source code was originally written by Dr.Sumio Morioka for use in the Nov 2014 issue of 
00006  * "the Interface magazine", published by CQ publishing Co.Ltd in Japan (http://www.cqpub.co.jp).
00007  * The author has no responsibility on any results caused by using this code.
00008  *
00009  * - Distribution date of this code: Sep 24, 2014
00010  * - Author: Dr.Sumio Morioka (http://www002.upp.so-net.ne.jp/morioka)
00011  *
00012  *
00013  * IMPORTANT NOTICE:
00014  * Redistribution and use in source and binary forms, with or without
00015  * modification, are permitted provided that the following conditions are met:
00016  *   * Redistributions of source code must retain the above copyright
00017  *     notice, this list of conditions and the following disclaimer.
00018  *   * Redistributions in binary form must reproduce the above copyright
00019  *     notice, this list of conditions and the following disclaimer in the
00020  *     documentation and/or other materials provided with the distribution.
00021  *   * Neither the name of the copyright holder nor the
00022  *     names of its contributors may be used to endorse or promote products
00023  *     derived from this software without specific prior written permission.
00024  *
00025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00026  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00027  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00028  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
00029  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00030  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00031  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00032  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00033  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00034  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035  */
00036  
00037 #include "mbed.h"
00038 #include "TextLCD.h"
00039 #include "LocalFileSystem.h"
00040 
00041 #include "ov7670.h"
00042 
00043 TextLCD lcd(p24, p26, p27, p28, p29, p30);
00044 DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4);
00045 PwmOut sv0(p21), sv1(p22), sv2(p23);
00046 
00047 LocalFileSystem local("webfs");
00048 
00049 OV7670 camera(
00050     p9,p10,         // SDA,SCL(I2C / SCCB)
00051     p5,p6,p7,       // VSYNC,HREF,WEN(FIFO)
00052     p20,p19,p18,p17,p16,p15,p14,p13,    // D7-D0
00053     p8,p11,p12);    // RRST,OE,RCLK
00054 
00055 Timer tmr;
00056 
00057 //#define QQVGA
00058 #define QVGA
00059 //#define VGA34
00060 
00061 #ifdef QQVGA
00062 #define SIZEX 160
00063 #define SIZEY 120
00064 #endif
00065 
00066 #ifdef QVGA
00067 #define SIZEX 320
00068 #define SIZEY 240
00069 #endif
00070 
00071 #ifdef VGA34
00072 #define SIZEX 480
00073 #define SIZEY 360
00074 #endif
00075 
00076 
00077 #define SHUTTER_THRESHOLD   3500    // # of skin color pixels
00078 
00079 
00080 /////////////////////////////////////////////////////////////////////////////////
00081 
00082 void rgb2hsv(
00083     unsigned char   rval,
00084     unsigned char   gval,
00085     unsigned char   bval,
00086 
00087     unsigned char   *hval,
00088     unsigned char   *sval,
00089     unsigned char   *vval
00090 )
00091 {
00092     unsigned char   max, min;
00093     int             ret;
00094 
00095     max = (rval >= gval) ? rval : gval;
00096     max = (bval >= max)  ? bval : max;
00097 
00098     min = (rval <= gval) ? rval : gval;
00099     min = (bval <= min)  ? bval : min;
00100 
00101     ///////////////////////////////////////////
00102     // compute H
00103     ///////////////////////////////////////////
00104     if (max == min)
00105         ret = 0;    // (undef)
00106     else if (rval >= gval && rval >= bval)  // max: R
00107         ret = ((gval - bval) * 60) / (max - min);
00108     else if (gval >= rval && gval >= bval)  // max: G
00109         ret = ((bval - rval) * 60) / (max - min) + 120;
00110     else    // max: B
00111         ret = ((rval - gval) * 60) / (max - min) + 240;
00112 
00113     ret %= 360;
00114     if (ret < 0)
00115         ret += 360;
00116 
00117     *hval   = (ret * 255) / 360;
00118 
00119     ///////////////////////////////////////////
00120     // compute S
00121     ///////////////////////////////////////////
00122     if (max == 0)
00123         ret = 0;    // (undef)
00124     else
00125         ret = ((max - min) * 255) / max;
00126 
00127     *sval   = ret;
00128 
00129     ///////////////////////////////////////////
00130     // compute V
00131     ///////////////////////////////////////////
00132     *vval   = max;
00133 }
00134 
00135 /////////////////////////////////////////////////////////////////////////////////
00136 
00137 unsigned char judge_skin_color(
00138     unsigned char   hval,
00139     unsigned char   sval,
00140     unsigned char   vval
00141 )
00142 {
00143     if (hval <= 70 && sval >= 25 && sval <= 70 && vval >= 180 && vval <= 250)   // <rgain,ggain,bgain> == <0x48,0x40,0x60>
00144         return (255);
00145     else
00146         return (0);
00147 }
00148 
00149 /////////////////////////////////////////////////////////////////////////////////
00150 
00151 typedef unsigned char (*kernel_func)(unsigned char *linebuf, int x, int y, int line_size, int kernel_size, void *param);    // kernel operation function
00152 
00153 typedef struct _stream_filter
00154 {
00155     // input pixel data
00156     unsigned char   d_in0;          // plane 0
00157     unsigned char   d_in1;          // plane 1
00158     unsigned char   d_in2;          // plane 2
00159     unsigned char   d_in_attr;      // data attribute (see the definitions below)
00160 
00161     // output pixel data
00162     unsigned char   d_out0;         // plane 0
00163     unsigned char   d_out1;         // plane 1
00164     unsigned char   d_out2;         // plane 2
00165     unsigned char   d_out_attr;     // data attribute (see the definitions below)
00166 
00167     // output data
00168     char            is_3_planes;    // 0: single plane, Others: 3 planes
00169 
00170     ////////////////////////////////////////
00171     // internal variables (do not touch)
00172     ////////////////////////////////////////
00173     char            state;          // internal 
00174 
00175     int             d_in_cnt;       // # of total input
00176     int             d_in_x;         // x-coordinate of input position on "line_buf" (not on entire screen)
00177     int             d_in_y;         // y-coordinate
00178 
00179     int             d_out_cnt;      // # of total output
00180     int             d_out_x;        // x-coordinate of center of kernel on "line_buf" (not on entire screen)
00181     int             d_out_y;        // y-coordinate
00182 
00183     int             line_size;      // width
00184     int             kernel_size;    // kernel size (MUST be odd)
00185 
00186     unsigned char   *line_buf0;     // line buffer for plane 0
00187     unsigned char   *line_buf1;     // plane 1
00188     unsigned char   *line_buf2;     // plane 2
00189 
00190     kernel_func     func;           // pointer to a kernel operation function
00191     void            *func_param;    // parameter to the above function (ex. pointer to coefficient matrix etc.)
00192 } stream_filter;
00193 
00194 
00195 #define ATTR_1ST        0       // 1st pixel data
00196 #define ATTR_VALID      1       // valid pixel data (not 1st nor last)
00197 #define ATTR_LAST       2       // last pixel data
00198 #define ATTR_INVALID    3       // invalid pixel data
00199 
00200 #define STATE_PROCESS   0       // do not touch
00201 #define STATE_FLUSH     1       // do not touch
00202 
00203 #ifdef DEBUG
00204 FILE *fp_his;
00205 #endif  // DEBUG
00206 
00207 
00208 ///////////////////--> kernel func
00209 unsigned char comb_filter(unsigned char *linebuf, int x, int y, int line_size, int kernel_size, void *matrix_void)
00210 {
00211     float   acc     = 0.0f;
00212     int     mat_idx = 0;
00213 
00214     ////////////////////////////////////////////// ---> customize here
00215     float   *matrix = (float *)matrix_void;
00216     ////////////////////////////////////////////// <--- customize here
00217 
00218 #ifdef DEBUG
00219     fprintf(fp_his, "\tpixel: ");
00220 #endif
00221 
00222     // scan kernel
00223     for (int ky = y - ((kernel_size - 1) / 2); ky <= y + (kernel_size - 1) / 2; ky++) {
00224         int     ly;
00225         // (rounding linebuf)
00226         if (ky < 0)
00227             ly  = ky + (kernel_size + 1);
00228         else if (ky >= kernel_size + 1)
00229             ly  = ky - (kernel_size + 1);
00230         else
00231             ly  = ky;
00232 
00233         for (int kx = x - ((kernel_size - 1) / 2); kx <= x + (kernel_size - 1) / 2; kx++, mat_idx++) {
00234             if (kx >= 0 && kx < line_size) {
00235                 float   pixel;
00236                 pixel   = (float)(*(linebuf + (ly * line_size) + kx));
00237 
00238                 ////////////////////////////////////////////// ---> customize here
00239 #ifdef DEBUG
00240                 fprintf(fp_his, "%02x ", *(linebuf + (ly * line_size) + kx));
00241 #endif
00242                 acc     += pixel * (*(matrix + mat_idx));
00243                 ////////////////////////////////////////////// <--- customize here
00244             }
00245         }
00246 
00247 #ifdef DEBUG
00248         fprintf(fp_his, ", ");
00249 #endif
00250     }
00251 
00252 #ifdef DEBUG
00253     fprintf(fp_his, "(ret %d)\n", (unsigned char)(acc + 0.5f));
00254 #endif
00255 
00256     return ((unsigned char)(acc + 0.5f));
00257 }
00258 ///////////////////<-- kernel func
00259 
00260 
00261 void dump_stream_filter(FILE *fp, stream_filter *flt)   // for debug; dump contents of the structure data
00262 {
00263     fprintf(fp, "d_in %02x ", flt->d_in0);
00264     if (flt->d_in_attr == ATTR_1ST)             fprintf(fp, "ATTR_1ST");
00265     else if (flt->d_in_attr == ATTR_VALID)      fprintf(fp, "ATTR_VALID");
00266     else if (flt->d_in_attr == ATTR_LAST)       fprintf(fp, "ATTR_LAST");
00267     else if (flt->d_in_attr == ATTR_INVALID)    fprintf(fp, "ATTR_INVALID");
00268     else                                        fprintf(fp, "illegal attribute");
00269     fprintf(fp, "\tcnt %d, x %d, y %d\n", flt->d_in_cnt, flt->d_in_x, flt->d_in_y);
00270 
00271     fprintf(fp, "d_out %02x ", flt->d_out0);
00272     if (flt->d_out_attr == ATTR_1ST)            fprintf(fp, "ATTR_1ST");
00273     else if (flt->d_out_attr == ATTR_VALID)     fprintf(fp, "ATTR_VALID");
00274     else if (flt->d_out_attr == ATTR_LAST)      fprintf(fp, "ATTR_LAST");
00275     else if (flt->d_out_attr == ATTR_INVALID)   fprintf(fp, "ATTR_INVALID");
00276     else                                        fprintf(fp, "illegal attribute");
00277     fprintf(fp, "\tcnt %d, x %d, y %d\n", flt->d_out_cnt, flt->d_out_x, flt->d_out_y);
00278 
00279     if (flt->state == STATE_PROCESS)            fprintf(fp, "state: STATE_PROCESS\n");
00280     else                                        fprintf(fp, "state: STATE_FLUSH\n");
00281 
00282     fprintf(fp, "\n");
00283     for (int y = 0; y < flt->kernel_size + 1; y++) {
00284         for (int x = 0; x < flt->line_size; x++) {
00285             fprintf(fp, "%02x ", *(flt->line_buf0 + (y * flt->line_size) + x) );
00286         }
00287         fprintf(fp, "\n");
00288     }
00289 
00290     if (flt->is_3_planes != 0) {
00291         fprintf(fp, "\n");
00292         for (int y = 0; y < flt->kernel_size + 1; y++) {
00293             for (int x = 0; x < flt->line_size; x++) {
00294                 fprintf(fp, "%02x ", *(flt->line_buf1 + (y * flt->line_size) + x) );
00295             }
00296             fprintf(fp, "\n");
00297         }
00298 
00299         fprintf(fp, "\n");
00300         for (int y = 0; y < flt->kernel_size + 1; y++) {
00301             for (int x = 0; x < flt->line_size; x++) {
00302                 fprintf(fp, "%02x ", *(flt->line_buf1 + (y * flt->line_size) + x) );
00303             }
00304             fprintf(fp, "\n");
00305         }
00306     }
00307 
00308     fprintf(fp, "====================================================\n");
00309     fflush(fp);
00310 }
00311 
00312 
00313 // reset data structure for reuse
00314 void reset_stream_filter(stream_filter *flt)
00315 {
00316     if (flt == (stream_filter *)NULL)
00317         return;
00318 
00319     flt->state          = STATE_PROCESS;
00320 
00321     flt->d_in_cnt       = 0;                                // total # of data
00322     flt->d_in_x         = 0;                                // linebuf pointer
00323     flt->d_in_y         = (flt->kernel_size - 1) / 2;       // linebuf pointer
00324 
00325     flt->d_out_cnt      = 0;                                // total # of data
00326     flt->d_out_x        = 0;                                // linebuf pointer
00327     flt->d_out_y        = (flt->kernel_size - 1) / 2;       // linebuf pointer
00328 
00329     // zero clear buffer
00330     if (flt->line_buf0 != (unsigned char *)NULL) {
00331         for (int i = 0; i < flt->line_size * (flt->kernel_size + 1); i++) {
00332             *(flt->line_buf0 + i)   = 0;
00333         }
00334     }
00335 
00336     if (flt->line_buf1 != (unsigned char *)NULL) {
00337         for (int i = 0; i < flt->line_size * (flt->kernel_size + 1); i++) {
00338             *(flt->line_buf1 + i)   = 0;
00339         }
00340     }
00341 
00342     if (flt->line_buf2 != (unsigned char *)NULL) {
00343         for (int i = 0; i < flt->line_size * (flt->kernel_size + 1); i++) {
00344             *(flt->line_buf2 + i)   = 0;
00345         }
00346     }
00347 }
00348 
00349 
00350 // allocate and initialize data structure
00351 stream_filter *create_stream_filter(char is_3_planes, int line_size, int kernel_size, kernel_func func, void *func_param)
00352 {
00353     stream_filter   *ret;
00354 
00355     // allocate memory
00356     if ((ret = (stream_filter *)malloc(sizeof (stream_filter))) == (stream_filter *)NULL)
00357         return ((stream_filter *)NULL);
00358 
00359     if ((ret->line_buf0 = (unsigned char *)malloc(sizeof (unsigned char) * line_size * (kernel_size + 1))) == (unsigned char *)NULL) {
00360         free(ret);
00361         return ((stream_filter *)NULL);
00362     }
00363 
00364     if (is_3_planes != 0) {
00365         if ((ret->line_buf1 = (unsigned char *)malloc(sizeof (unsigned char) * line_size * (kernel_size + 1))) == (unsigned char *)NULL) {
00366             free(ret->line_buf0);
00367             free(ret);
00368             return ((stream_filter *)NULL);
00369         }
00370 
00371         if ((ret->line_buf2 = (unsigned char *)malloc(sizeof (unsigned char) * line_size * (kernel_size + 1))) == (unsigned char *)NULL) {
00372             free(ret->line_buf0);
00373             free(ret->line_buf1);
00374             free(ret);
00375             return ((stream_filter *)NULL);
00376         }
00377     }
00378     else {
00379         ret->line_buf1  = (unsigned char *)NULL;
00380         ret->line_buf2  = (unsigned char *)NULL;
00381     }
00382 
00383     // init internal valiables
00384     ret->is_3_planes    = is_3_planes;
00385     ret->line_size      = line_size;
00386     ret->kernel_size    = kernel_size;
00387 
00388     reset_stream_filter(ret);
00389 
00390     // init kernel operation func
00391     ret->func       = func;
00392     ret->func_param = func_param;
00393 
00394     return (ret);
00395 }
00396 
00397 
00398 // process 1 pixel; Set d_in & d_in_attr before calling. The result will be set to d_out & d_out_attr.
00399 void apply_filter(stream_filter *flt)
00400 {
00401     if (flt == (stream_filter *)NULL)
00402         return;
00403 
00404     if ((flt->state == STATE_PROCESS && flt->d_in_attr != ATTR_INVALID)
00405             || (flt->state == STATE_FLUSH && flt->d_in_attr == ATTR_INVALID)) {
00406         /////////////////////////////////////////////
00407         // store d_in to linebuf
00408         /////////////////////////////////////////////
00409         if (flt->d_in_attr == ATTR_INVALID) {
00410             flt->d_in0  = 0;
00411             flt->d_in1  = 0;
00412             flt->d_in2  = 0;
00413         }
00414 
00415         *(flt->line_buf0 + (flt->d_in_y * flt->line_size) + flt->d_in_x)    = flt->d_in0;
00416         if (flt->is_3_planes != 0) {
00417             *(flt->line_buf1 + (flt->d_in_y * flt->line_size) + flt->d_in_x)    = flt->d_in1;
00418             *(flt->line_buf2 + (flt->d_in_y * flt->line_size) + flt->d_in_x)    = flt->d_in2;
00419         }
00420 
00421         // update input counter
00422         if (flt->state == STATE_PROCESS && flt->d_in_attr != ATTR_LAST)
00423             (flt->d_in_cnt)++;
00424 
00425         // update input pointer
00426         (flt->d_in_x)++;
00427         if (flt->d_in_x >= flt->line_size) {
00428             flt->d_in_x = 0;
00429             (flt->d_in_y)++;
00430             if (flt->d_in_y >= flt->kernel_size + 1) {
00431                 flt->d_in_y = 0;
00432             }
00433         }
00434 
00435         /////////////////////////////////////////////
00436         // calc output (NOTE: do after updating input counter)
00437         /////////////////////////////////////////////
00438         if ((flt->state == STATE_PROCESS && flt->d_in_cnt > flt->line_size * (flt->kernel_size + 1) / 2)
00439                 || (flt->state == STATE_FLUSH && flt->d_in_cnt >= flt->d_out_cnt)) {    // normal operation
00440 
00441             // generate output (call kernel_operation func)
00442             flt->d_out0 = (flt->func)(flt->line_buf0, flt->d_out_x, flt->d_out_y, flt->line_size, flt->kernel_size, flt->func_param);
00443             if (flt->is_3_planes != 0) {
00444                 flt->d_out1 = (flt->func)(flt->line_buf1, flt->d_out_x, flt->d_out_y, flt->line_size, flt->kernel_size, flt->func_param);
00445                 flt->d_out2 = (flt->func)(flt->line_buf2, flt->d_out_x, flt->d_out_y, flt->line_size, flt->kernel_size, flt->func_param);
00446             }
00447 
00448             if (flt->d_out_cnt == 0)
00449                 flt->d_out_attr = ATTR_1ST;
00450             else if (flt->d_out_cnt == flt->d_in_cnt)
00451                 flt->d_out_attr = ATTR_LAST;
00452             else
00453                 flt->d_out_attr = ATTR_VALID;
00454 
00455             // update output counter
00456             (flt->d_out_cnt)++;
00457 
00458             // update output pointer
00459             (flt->d_out_x)++;
00460             if (flt->d_out_x >= flt->line_size) {
00461                 flt->d_out_x    = 0;
00462                 (flt->d_out_y)++;
00463                 if (flt->d_out_y >= flt->kernel_size + 1) {
00464                     flt->d_out_y    = 0;
00465                 }
00466             }
00467         }
00468         else {  // initial operation (still filling buffer) or completion of data output
00469             // no output
00470             flt->d_out0     = 0;
00471             flt->d_out1     = 0;
00472             flt->d_out2     = 0;
00473             flt->d_out_attr = ATTR_INVALID;
00474         }
00475 
00476         /////////////////////////////////////////////
00477         // change state
00478         /////////////////////////////////////////////
00479         if (flt->state == STATE_PROCESS && flt->d_in_attr == ATTR_LAST) {
00480             flt->state  = STATE_FLUSH;
00481         }
00482     }
00483 }
00484 
00485 
00486 // release data structure
00487 void release_stream_filter(stream_filter *flt)
00488 {
00489     if (flt == (stream_filter *)NULL)
00490         return;
00491     if (flt->line_buf0 != (unsigned char *)NULL)
00492         free(flt->line_buf0);
00493     free(flt);
00494 }
00495 
00496 
00497 /////////////////////////////////////////////////////////////////////////////////
00498 
00499 
00500 //void cam_cap(void);
00501 int cam_cap(char, stream_filter *);
00502 
00503 
00504 int memfree(void)
00505 {
00506     int ret = 1;
00507     while (1) {
00508         char    *p  = (char *)malloc(ret);
00509         if (p == NULL)
00510             break;
00511         free(p);
00512         ret++;
00513     }
00514     return (ret - 1);
00515 }
00516 
00517 
00518 int main() 
00519 {
00520     led1 = 0;
00521     led2 = 0;
00522     led3 = 0;
00523     led4 = 0;
00524 
00525     sv0.period_us(20000);       // 20ms
00526     sv0.pulsewidth_us(5000);    // 5ms
00527 
00528     sv1.period_us(20000);       // 20ms
00529     sv1.pulsewidth_us(10000);   // 10ms
00530 
00531     sv2.period_us(20000);       // 20ms
00532     sv2.pulsewidth_us(15000);   // 15ms
00533     
00534     ////////////////////////////////////////////////////////////////////////////
00535     camera.WriteReg(0x12, 0x80);            // com7; reset
00536     wait_ms(200);
00537 
00538     camera.InitDefaultReg();
00539 
00540     // negate vsync
00541     camera.WriteReg(0x15, 0x02);            // com10; negative vsync
00542 
00543 #ifdef QQVGA
00544     camera.InitQQVGA();
00545 #endif
00546 #ifdef QVGA
00547     camera.InitQVGA();
00548 #endif
00549 #ifdef VGA34
00550     camera.InitVGA_3_4();
00551 #endif
00552 
00553     // data format
00554     camera.WriteReg(0x12, 0x04 + 0);    // com7 RGB (bit1...test pattern)
00555     camera.WriteReg(0x40, 0xD0);    // com15 RGB565
00556     camera.WriteReg(0x8c, 0x00);    // RGB444
00557 
00558     // turn off AWB
00559     unsigned char tmp = camera.ReadReg(0x13);   // COM8
00560     camera.WriteReg(0x13, tmp & 0xFD);          // COM8[1] = 0
00561     camera.WriteReg(0x02, 0x48);                // R gain
00562     camera.WriteReg(0x6A, 0x40);                // G gain
00563     camera.WriteReg(0x01, 0x60);                // B gain
00564 
00565     wait_ms(300);
00566 
00567     // discard some first frames
00568     for (int i = 0; i < 10; i++) {
00569         camera.CaptureNext();   // sample start!
00570         while(camera.CaptureDone() == false)
00571             ;
00572     }
00573 
00574     //////////////////////////////////////////////////
00575     int blur_kernel_size        = 7;
00576 
00577     float blur_matrix[] = {
00578         // Average filter
00579         // Change here in order to use a different filter
00580         0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f,
00581         0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f,
00582         0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f,
00583         0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f,
00584         0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f,
00585         0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f,
00586         0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f
00587     };
00588 
00589     int prev_mem    = memfree();
00590 
00591     stream_filter *average_flt;
00592     average_flt = create_stream_filter(0, SIZEX, blur_kernel_size, comb_filter, (void *)blur_matrix);   // 0: 1 plane
00593 
00594 //  tmr.start();    // timer
00595 //  cam_cap(0, average_flt);
00596 //  tmr.stop();     // timer
00597 
00598     int cur_mem = memfree();
00599 
00600 //  lcd.locate(0, 0);
00601 //  lcd.printf("%dms", tmr.read_ms());
00602 
00603 //  lcd.locate(0, 1);
00604 //  lcd.printf("m %d, %d", prev_mem, cur_mem);
00605 
00606 //char shot_flag = 0;
00607 
00608     //////////////////////////////////////////////////
00609     while (1) {
00610 //      int rgain, ggain, bgain; 
00611         int skin_pixel_num;
00612 
00613         led1 = 1;
00614         reset_stream_filter(average_flt);
00615 
00616         tmr.reset();
00617         tmr.start();
00618         skin_pixel_num  = cam_cap(0, average_flt);
00619         tmr.stop();
00620 
00621         if (skin_pixel_num >= SHUTTER_THRESHOLD)    {   // threshold
00622             cam_cap(1, average_flt);    // shot
00623 
00624             lcd.locate(0, 0);
00625             lcd.printf("CAPTURED ");
00626             lcd.locate(0, 1);
00627             lcd.printf("val %d ", skin_pixel_num);
00628 
00629             while (1) {
00630                 wait(1);
00631             }
00632         }
00633 //      cur_mem = memfree();
00634 
00635 //      rgain   = camera.ReadReg(0x02);
00636 //      ggain   = camera.ReadReg(0x6A);
00637 //      bgain   = camera.ReadReg(0x01);
00638 
00639         lcd.locate(0, 0);
00640         lcd.printf("%dms ", tmr.read_ms());
00641         lcd.locate(0, 1);
00642         lcd.printf("val %d ", skin_pixel_num);
00643 //      lcd.printf("%dms, M%d ", tmr.read_ms(), cur_mem);
00644 //      lcd.printf("R%02x G%02x B%02x", rgain, ggain, bgain);
00645 
00646 //      wait_ms(100);
00647    }
00648 
00649 }
00650 
00651 
00652 void write_bmp_header(FILE *fp_bmp)
00653 {
00654     /////////////////////////
00655     // file header
00656     /////////////////////////
00657     fprintf(fp_bmp, "BM");
00658     int val = 14 + 40 + SIZEX * SIZEY * 3;   // file size
00659     fprintf(fp_bmp, "%c%c%c%c", val % 0x100, val / 0x100, val / 0x10000, val / 0x1000000);
00660     fprintf(fp_bmp, "%c%c%c%c%c%c%c%c", 0, 0, 0, 0, 0x36, 0, 0, 0);
00661 
00662     /////////////////////////
00663     // information header
00664     /////////////////////////
00665     fprintf(fp_bmp, "%c%c%c%c", 0x28, 0, 0, 0);  // header size
00666     fprintf(fp_bmp, "%c%c%c%c", SIZEX % 0x100, SIZEX / 0x100, SIZEX / 0x10000, SIZEX / 0x1000000);
00667     fprintf(fp_bmp, "%c%c%c%c", SIZEY % 0x100, SIZEY / 0x100, SIZEY / 0x10000, SIZEY / 0x1000000);
00668     fprintf(fp_bmp, "%c%c", 1, 0);               // # of plane
00669     fprintf(fp_bmp, "%c%c", 24, 0);              // bit count
00670     fprintf(fp_bmp, "%c%c%c%c", 0, 0, 0, 0);     // compression
00671     val = SIZEX * SIZEY * 3;         // data size
00672     fprintf(fp_bmp, "%c%c%c%c", val % 0x100, val / 0x100, val / 0x10000, val / 0x1000000);
00673     fprintf(fp_bmp, "%c%c%c%c", 0, 0, 0, 0);
00674     fprintf(fp_bmp, "%c%c%c%c", 0, 0, 0, 0);
00675     fprintf(fp_bmp, "%c%c%c%c", 0, 0, 0, 0);
00676     fprintf(fp_bmp, "%c%c%c%c", 0, 0, 0, 0);
00677 }
00678 
00679 
00680 void write_bmp_data(FILE *fp_bmp, unsigned char b, unsigned char g, unsigned char r)
00681 {
00682     fprintf(fp_bmp, "%c%c%c", b, g, r);
00683 }
00684 
00685 
00686 //void cam_cap(Arguments* input, Reply* output)
00687 int cam_cap(char file_flag, stream_filter *average_flt)
00688 {
00689     FILE *fp_bmp;
00690     unsigned int d1, d2;
00691     unsigned char sort[3];
00692 
00693     int dx  = 0;
00694     int dy  = 0;
00695 
00696     unsigned int    skin_pixel_num  = 0;
00697     unsigned int    skin_x          = 0;
00698     unsigned int    skin_y          = 0;
00699 
00700 
00701     ////////////////////////////////////////////////////////////////////
00702     led2 = 0;
00703     led3 = 0;
00704     led4 = 0;
00705 
00706     if (file_flag != 0) {
00707         fp_bmp  = fopen("/webfs/cam.bmp", "wb");
00708         write_bmp_header(fp_bmp);
00709     }
00710 
00711     camera.CaptureNext();   // sample start!
00712 
00713     while(camera.CaptureDone() == false)
00714         ;
00715 
00716     camera.ReadStart();     // reset pointer
00717 
00718     led2 = 1;
00719 
00720     /////////////////////////////////////////////
00721     // main loop
00722     /////////////////////////////////////////////
00723     for (int y = 0; y < SIZEY; y++) {    
00724         for (int x = 0; x < SIZEX; x++) {
00725             d1 = camera.ReadOneByte() ; // upper nibble is XXX , lower nibble is B
00726             d2 = camera.ReadOneByte() ; // upper nibble is G   , lower nibble is R
00727 
00728             /////////////////////////////////////////////
00729             // RGB565
00730             /////////////////////////////////////////////
00731             sort[0] = ((d1 & 0xF8) >> 3) << 3;      // R
00732             sort[1] = ( ((d1 & 0x07) << 3) + ((d2 & 0xE0) >> 5) ) << 2;     // G
00733             sort[2] = (d2 & 0x1F) << 3;             // B
00734 
00735             //////////////////////////////////////////////////////////////////////////
00736             // 1. get input
00737             //////////////////////////////////////////////////////////////////////////
00738             unsigned char   b0  = sort[2];
00739             unsigned char   g0  = sort[1];
00740             unsigned char   r0  = sort[0];
00741 
00742             if (file_flag != 0) {
00743                 write_bmp_data(fp_bmp, sort[2], sort[1], sort[0]);      // B,G,R
00744             }
00745             else {
00746                 //////////////////////////////////////////////////////////////////////////
00747                 // 2. RGB2HSV
00748                 //////////////////////////////////////////////////////////////////////////
00749                 unsigned char   h1, s1, v1;
00750                 rgb2hsv(r0, g0, b0, &h1, &s1, &v1);
00751 
00752                 //////////////////////////////////////////////////////////////////////////
00753                 // 3. judge
00754                 //////////////////////////////////////////////////////////////////////////
00755                 unsigned char   val2    = judge_skin_color(h1, s1, v1);
00756 
00757                 //////////////////////////////////////////////////////////////////////////
00758                 // 4. blur (average)
00759                 //////////////////////////////////////////////////////////////////////////
00760                 average_flt->d_in0  = val2;     // (1 plane mode; use d_in0 only)
00761 
00762                 if (y == 0 && x == 0)
00763                     average_flt->d_in_attr  = ATTR_1ST;
00764                 else if (y == SIZEY - 1 && x == SIZEX - 1)
00765                     average_flt->d_in_attr  = ATTR_LAST;
00766                 else
00767                     average_flt->d_in_attr  = ATTR_VALID;
00768 
00769                 // apply filter
00770                 apply_filter(average_flt);
00771 
00772                 //////////////////////////////////////////////////////////////////////////
00773                 // 5. limit
00774                 //////////////////////////////////////////////////////////////////////////
00775                 unsigned char   val3    = average_flt->d_out0;
00776 
00777                 if (val3 < 220)
00778                     val3    = 0;
00779                 else {
00780                     skin_pixel_num++;
00781                     skin_x  += dx;
00782                     skin_y  += dy;
00783                 }
00784 
00785                 //////////////////////////////////////////////////////////////////////////
00786                 // 6. put output
00787                 //////////////////////////////////////////////////////////////////////////
00788                 if (average_flt->d_out_attr != ATTR_INVALID) {
00789                     sort[2] = val3 & b0;
00790                     sort[1] = val3 & g0;
00791                     sort[0] = val3 & r0;
00792 
00793                     dx++;
00794                     if (dx == SIZEX) {
00795                         dx  = 0;
00796                         dy++;
00797                     }
00798                 }
00799             }   // file_flag
00800 
00801         }
00802     }
00803 
00804     led3 = 1;
00805 
00806     if (file_flag != 0) {
00807         /////////////////////////////////////////////
00808         // flush filter
00809         /////////////////////////////////////////////
00810         average_flt->d_in_attr  = ATTR_INVALID;
00811 
00812         while (1) {
00813             apply_filter(average_flt);
00814 
00815             if (average_flt->d_out_attr == ATTR_INVALID)
00816                 break;
00817 
00818             //////////////////////////////////////////////////////////////////////////
00819             // 5. limit
00820             //////////////////////////////////////////////////////////////////////////
00821             unsigned char   val3    = average_flt->d_out0;
00822 
00823             if (val3 < 220)
00824                 val3    = 0;
00825             else {
00826                 skin_pixel_num++;
00827                 skin_x  += dx;
00828                 skin_y  += dy;
00829             }
00830 
00831             //////////////////////////////////////////////////////////////////////////
00832             // 6. put output
00833             //////////////////////////////////////////////////////////////////////////
00834             sort[2] = val3;
00835             sort[1] = val3;
00836             sort[0] = val3;
00837 
00838             dx++;
00839             if (dx == SIZEX) {
00840                 dx  = 0;
00841                 dy++;
00842             }
00843         }
00844     }
00845 
00846     led4 = 1;
00847 
00848     /////////////////////////////////////////////
00849     // end
00850     /////////////////////////////////////////////
00851     camera.ReadStop();
00852 
00853 //  release_stream_filter(average_flt);
00854 
00855     if (skin_pixel_num != 0) {
00856         skin_x  /= skin_pixel_num;
00857         skin_y  /= skin_pixel_num;
00858     }
00859     else {
00860         skin_x  = SIZEX / 2;
00861         skin_y  = SIZEY / 2;
00862     }
00863 
00864     if (file_flag != 0) {
00865         fclose(fp_bmp);
00866     }
00867 
00868 //  led2 = 0;
00869 //  led3 = 0;
00870 //  led4 = 0;
00871 
00872     return (skin_pixel_num);
00873 }
00874 
00875 // end of file