Italiano
HOME | PROGETTI | CLASSI C++ | Sorgenti c\c++ | Galleria | Guestbook | Server BW | Contattami | Login

<< Webcam Viewer >>

visiste: 5007


Webcam Viewer è un programma che mostra come interfacciarsi con la webcam in Windows. Mostra anche come applicare il filtro di Sobel per l'edge detection in tempo reale.

Il programma è stato scritto per funzionare con la webcam di un Acer Aspire 3810t, precisamente il programma può funzionare solo con webcam che supportano il formato di compressione 0x32595559 (yuy2, 16 bit) con risoluzione 640x400.
Si puo rendere facilmente compatibile con qualche piccola modifica al formato rgb 24bit poiche la parte del programma che visualizza l'immagine lavora con questo formato.



  1. #define VERSIONE_PROGRAMMA "Webcam Viewer v0.01.01"
  2.  
  3. #include <cstdlib>
  4. #include <iostream>
  5. #include <windows.h>
  6. #include <string.h>
  7. #include <math.h>
  8. #include <time.h>
  9.  
  10. using namespace std;
  11.  
  12. //webcam
  13. #include <Vfw.h>
  14. #pragma comment(lib,"Vfw32.lib")
  15.  
  16. //gtk+
  17. #include <gtk/gtk.h>
  18. #pragma comment(lib,"atk-1.0.lib")
  19. #pragma comment(lib,"cairo.lib")
  20. #pragma comment(lib,"gio-2.0.lib")
  21. #pragma comment(lib,"glib-2.0.lib")
  22. #pragma comment(lib,"gmodule-2.0.lib")
  23. #pragma comment(lib,"gobject-2.0.lib")
  24. #pragma comment(lib,"gthread-2.0.lib")
  25. #pragma comment(lib,"gailutil.lib")
  26. #pragma comment(lib,"gdk_pixbuf-2.0.lib")
  27. #pragma comment(lib,"gdk-win32-2.0.lib")
  28. #pragma comment(lib,"gtk-win32-2.0.lib")
  29. #pragma comment(lib,"pango-1.0.lib")
  30. #pragma comment(lib,"pangocairo-1.0.lib")
  31. #pragma comment(lib,"pangoft2-1.0.lib")
  32. #pragma comment(lib,"pangowin32-1.0.lib")
  33.  
  34. //macro
  35. inline char char_conversion(int c){ return ( (c)<255) ? (c) : 255; }
  36.  
  37. //variabili
  38. GtkWidget *finestra1;
  39. GtkWidget *draw_area, *draw_area_sobel;
  40. GtkWidget *area_box;
  41. PangoLayout *testo_draw_area;
  42.  
  43. long frame_count = 0;
  44. int global_frame_width;
  45. int global_frame_row_size;
  46. char *video_text;
  47. clock_t global_time_start, global_time_current;
  48.  
  49. guchar * bit24format;
  50. guchar * bit24format_sobel;
  51. long bit24format_size;
  52. unsigned char ****tabella_yuy2_rgb;
  53.  
  54. //funzioni
  55. int webcam();
  56. gboolean expose_event_callback (GtkWidget *widget, GdkEventExpose *event, gpointer data); //callback per drawing area
  57. LRESULT FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr); //callback per cap
  58.  
  59.  
  60. int main(int argc, char *argv[])
  61. {
  62. GError ** thread_error;
  63. thread_error = NULL;
  64.  
  65. if( ! g_thread_supported() )
  66. g_thread_init( NULL );
  67.  
  68. gtk_init (&argc, &argv);
  69. //********** FINESTRA1 *************//
  70. finestra1 = gtk_window_new(GTK_WINDOW_TOPLEVEL); //creo la finestra principale
  71. gtk_window_set_title(GTK_WINDOW(finestra1), VERSIONE_PROGRAMMA); //setto il titolo della finestra principale
  72. gtk_container_set_border_width(GTK_CONTAINER(finestra1), 3); //setto il bordo della finestra principale
  73. gtk_window_set_resizable(GTK_WINDOW(finestra1), FALSE); //rendo non resizable la finestra principale
  74. g_signal_connect(G_OBJECT(finestra1), "delete_event", G_CALLBACK(gtk_main_quit), NULL);
  75.  
  76. //box
  77. area_box = gtk_hbox_new(FALSE, 1);
  78.  
  79. draw_area = gtk_drawing_area_new();
  80. gtk_widget_set_size_request(draw_area, 640, 400);
  81. gtk_box_pack_start(GTK_BOX(area_box), draw_area, TRUE, TRUE, 0);
  82. g_signal_connect (G_OBJECT (draw_area), "expose_event", G_CALLBACK (expose_event_callback), NULL);
  83. testo_draw_area = gtk_widget_create_pango_layout(draw_area, "PangoLayout");
  84.  
  85. draw_area_sobel = gtk_drawing_area_new();
  86. gtk_widget_set_size_request(draw_area_sobel, 640, 400);
  87. gtk_box_pack_start(GTK_BOX(area_box), draw_area_sobel, TRUE, TRUE, 0);
  88. g_signal_connect (G_OBJECT (draw_area_sobel), "expose_event", G_CALLBACK (expose_event_callback), NULL);
  89.  
  90. gtk_container_add(GTK_CONTAINER(finestra1), area_box);
  91. gtk_widget_show_all(finestra1);
  92.  
  93. g_thread_create((GThreadFunc) webcam, NULL, 0, thread_error);
  94.  
  95. gtk_main();
  96. return EXIT_SUCCESS;
  97. }
  98.  
  99. int webcam(){
  100. long x,y,z,h;
  101. CAPSTATUS status;
  102.  
  103. LPBITMAPINFO video_format;
  104. DWORD dwSize;
  105.  
  106. HWND hwnd = capCreateCaptureWindow("Explorer", WS_ICONIC, 0, 0, 640, 400, NULL, 0);
  107. capDriverConnect(hwnd, 0);
  108. capPreviewRate(hwnd, 66); // rate, in milliseconds
  109. capPreview(hwnd, TRUE); // starts preview
  110. capSetCallbackOnFrame(hwnd, FrameCallbackProc);
  111.  
  112. //video format
  113. dwSize = capGetVideoFormatSize(hwnd);
  114. video_format = (LPBITMAPINFO) malloc (dwSize * sizeof(char));
  115. video_text = (char *) malloc(200 * sizeof(char));
  116. capGetVideoFormat(hwnd, video_format, dwSize);
  117.  
  118. printf("video format: bit per pixel: %d compressione: %d\n", video_format->bmiHeader.biBitCount, video_format->bmiHeader.biCompression);
  119.  
  120. if(video_format->bmiHeader.biBitCount != 16 || video_format->bmiHeader.biCompression != 844715353){
  121. printf("Video format non compatibile.\n");
  122. printf("formati supportati:\n");
  123. printf("1 - 16bit con compressione 844715353\n");
  124. return 0;
  125. }
  126.  
  127. //cap status
  128. capGetStatus(hwnd, &status, sizeof(CAPSTATUS));
  129. printf("cap status: %dx%d preview_status: %d\n", status.uiImageWidth, status.uiImageHeight, status.fLiveWindow);
  130.  
  131. bit24format_size = status.uiImageWidth*status.uiImageHeight*3;
  132. bit24format = new guchar[bit24format_size];
  133. bit24format_sobel = new guchar[bit24format_size];
  134. global_frame_width = status.uiImageWidth;
  135. global_frame_row_size = status.uiImageWidth*2;
  136.  
  137. //creazione tabella di conversione yuy2 to rgb
  138. printf("preparazione tabella yuy2 to rgb... ");
  139. tabella_yuy2_rgb = new unsigned char ***[3];
  140. for(h=0;h<3;h++){
  141. tabella_yuy2_rgb[h] = new unsigned char **[256];
  142. for(x=0;x<256;x++){
  143. tabella_yuy2_rgb[h][x] = new unsigned char *[256];
  144. for(y=0;y<256;y++)
  145. tabella_yuy2_rgb[h][x][y] = new unsigned char[256];
  146. }
  147. }
  148. for(x=0;x<256;x++)
  149. for(y=0;y<256;y++)
  150. for(z=0;z<256;z++){
  151. tabella_yuy2_rgb[0][x][y][z] = char_conversion(abs( x + 1.371*(y - 128) ));
  152. tabella_yuy2_rgb[1][x][y][z] = char_conversion(abs( x - 0.698*(y - 128) - 0.336*(z - 128) ));
  153. tabella_yuy2_rgb[2][x][y][z] = char_conversion(abs( x + 1.732*(z - 128) ));
  154. }
  155. printf("fatto!\n");
  156.  
  157. //inizio visualizzazione immagini
  158. global_time_start = clock();
  159. for(x=0;x<1000;x++){
  160. capGrabFrameNoStop(hwnd);
  161. //Sleep(5);
  162. }
  163.  
  164. capCaptureStop(hwnd);
  165. capSetCallbackOnFrame(hwnd, NULL);
  166. capDriverDisconnect(hwnd);
  167.  
  168. return 1;
  169. }
  170.  
  171. gboolean expose_event_callback(GtkWidget *widget, GdkEventExpose *event, gpointer data)
  172. {
  173. gdk_draw_arc (widget->window,
  174. widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
  175. TRUE,
  176. 0, 0, widget->allocation.width, widget->allocation.height,
  177. 0, 64 * 360);
  178. return TRUE;
  179. }
  180.  
  181. LRESULT FrameCallbackProc(HWND hWnd, LPVIDEOHDR frame) {
  182. register long x,y=0, dietro=0;
  183. int Y1, Y2, Cb, Cr;
  184. int vsobel, hsobel;
  185. unsigned char sobel;
  186. float angolo;
  187.  
  188. global_time_current = clock()-global_time_start;
  189. sprintf(video_text, "frame count: %d\ntime: %d ms\navarage frame rate: %.2f",
  190. frame_count, global_time_current, (float)frame_count*1000/global_time_current);
  191.  
  192. for(x=0;x<bit24format_size;){ //frame->lpData[y]
  193. Y1 = frame->lpData[y++];
  194. Cb = frame->lpData[y++];
  195. Y2 = frame->lpData[y++];
  196. Cr = frame->lpData[y++];
  197.  
  198. //***** normal video part
  199. bit24format[x++] = tabella_yuy2_rgb[0][Y1][Cr][Cb]; //red
  200. bit24format[x++] = tabella_yuy2_rgb[1][Y1][Cr][Cb]; //green
  201. bit24format[x++] = tabella_yuy2_rgb[2][Y1][Cr][Cb]; //blue
  202.  
  203. bit24format[x++] = tabella_yuy2_rgb[0][Y2][Cr][Cb]; //red
  204. bit24format[x++] = tabella_yuy2_rgb[1][Y2][Cr][Cb]; //green
  205. bit24format[x++] = tabella_yuy2_rgb[2][Y2][Cr][Cb]; //blue
  206.  
  207. //****** sobel part
  208. if(y > global_frame_row_size && y < frame->dwBytesUsed-global_frame_row_size){
  209. x -= 6;
  210.  
  211. //algoritmo di sobel
  212. hsobel = (int)
  213. frame->lpData[y-6-global_frame_row_size]
  214. - frame->lpData[y-2-global_frame_row_size]
  215. + frame->lpData[y-6] + frame->lpData[y-6]
  216. - frame->lpData[y-2] - frame->lpData[y-2]
  217. + frame->lpData[y-6+global_frame_row_size]
  218. - frame->lpData[y-2+global_frame_row_size]
  219. ;
  220. vsobel = (int)
  221. frame->lpData[y-6-global_frame_row_size]
  222. + frame->lpData[y-4-global_frame_row_size] + frame->lpData[y-4-global_frame_row_size]
  223. + frame->lpData[y-2-global_frame_row_size]
  224. - frame->lpData[y-6+global_frame_row_size]
  225. - frame->lpData[y-4+global_frame_row_size] - frame->lpData[y-4+global_frame_row_size]
  226. - frame->lpData[y-2+global_frame_row_size]
  227. ;
  228. sobel = char_conversion(abs(hsobel) + abs(vsobel));
  229.  
  230. bit24format_sobel[x++] = sobel;
  231. bit24format_sobel[x++] = sobel;
  232. bit24format_sobel[x++] = sobel;
  233.  
  234.  
  235. hsobel = (int)
  236. frame->lpData[y-4-global_frame_row_size]
  237. - frame->lpData[y-global_frame_row_size]
  238. + frame->lpData[y-4] + frame->lpData[y-4]
  239. - frame->lpData[y] - frame->lpData[y]
  240. + frame->lpData[y-4+global_frame_row_size]
  241. - frame->lpData[y+global_frame_row_size]
  242. ;
  243. vsobel = (int)
  244. frame->lpData[y-4-global_frame_row_size]
  245. + frame->lpData[y-2-global_frame_row_size] + frame->lpData[y-2-global_frame_row_size]
  246. + frame->lpData[y-global_frame_row_size]
  247. - frame->lpData[y-4+global_frame_row_size]
  248. - frame->lpData[y-2+global_frame_row_size] - frame->lpData[y-2+global_frame_row_size]
  249. - frame->lpData[y+global_frame_row_size]
  250. ;
  251. sobel = char_conversion(abs(hsobel) + abs(vsobel));
  252.  
  253. bit24format_sobel[x++] = sobel;
  254. bit24format_sobel[x++] = sobel;
  255. bit24format_sobel[x++] = sobel;
  256.  
  257. }
  258. }
  259.  
  260. gdk_draw_rgb_image(draw_area->window,
  261. draw_area->style->fg_gc[GTK_WIDGET_STATE(draw_area)],
  262. 0, 0, 640, 400, GDK_RGB_DITHER_NORMAL,
  263. bit24format, 640 * 3);
  264.  
  265. gdk_draw_rgb_image(draw_area_sobel->window,
  266. draw_area_sobel->style->fg_gc[GTK_WIDGET_STATE(draw_area_sobel)],
  267. 0, 0, 640, 400, GDK_RGB_DITHER_NORMAL,
  268. bit24format_sobel, 640 * 3);
  269.  
  270. pango_layout_set_text(testo_draw_area, video_text, strlen(video_text));
  271. gdk_draw_layout(draw_area->window, draw_area->style->fg_gc[GTK_WIDGET_STATE(draw_area)], 10, 10, testo_draw_area);
  272.  
  273.  
  274. frame_count++;
  275. return (LRESULT) TRUE ;
  276. }
  277.  
Versione sito: 1.03.01 by mamo139. - Tutti i sorgenti presenti su questo sito sono rilasciati sotto licenza "GNU GPL version 3".