English
HOME | PROJECTS | C++ CLASSES | c\c++ source code | Gallery | Guestbook | BW Servers | Contact me | Login

<< Webcam Viewer >>

visits: 5017


Webcam Viewer is a program that shows how to use the webcam in Windows. Moreover it shows how to use Sobel operator for edge detection in real time.

The program is written in order to work with the webcam of an Acer Aspire 3810t, precisely this program works with webcams that support the 0x32595559 compression format (yuy2, 16 bit) with a 640x400 resolution.
It can be easily modified in order to be compatible with a rgb 24bit format because the part of the program that displays the video works with this format.



  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.  
Website version: 1.03.01 by mamo139. - All the source codes are intended to be released under "GNU GPL version 3".