Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
Generated on Fri Jul 15 2022 06:43:31 by
1.7.2