- Target = demo_gtk
- SrcDir= .
- ExtList= .cpp .c
- Source= $(foreach ext,$(ExtList), \
- $(foreach sd, $(SrcDir), $(wildcard $(addprefix $(sd)/*,$(ext)))))
- Objs= $(foreach ext, $(ExtList), \
- $(patsubst %$(ext), %.o, $(filter %$(ext),$(Source))))
- CFLAGS := -Wall
- LIBS := -lrt -lpthread
- INCDIR := -I . -I /usr/include/publib -I/usr/include/jsoncpp/
- LIBS += -lopencv_core -lopencv_highgui -lopencv_ml -lopencv_imgproc -lopencv_video -lopencv_objdetect
- LIBS += `pkg-config --libs gtk+-2.0`
- INCDIR += -I /usr/include/opencv
- INCDIR += `pkg-config --cflags gtk+-2.0`
- CC=g++
- CPP=g++
- %.o : %.c
- $(CC) $(CFLAGS) -c $(@D)/$(<F) -o $(@D)/$(@F) $(INCDIR)
- %.o : %.cpp
- $(CPP) $(CFLAGS) -c $(@D)/$(<F) -o $(@D)/$(@F) $(INCDIR)
- $(Target): $(Objs)
- $(CC) -o $(Target) $(Objs) $(LIBS)
- all: $(Target)
- objs: $(Objs)
-
- RM= rm -rf
- clean:
- @$(RM) $(foreach sd, $(SrcDir), $(wildcard $(sd)/*.o))
- @$(RM) $(Target)
- cleanall:clean
- @$(RM) $(Target)
- rebuild: cleanall all
- #include <gtk/gtk.h>
- #include <glib/gstdio.h>
- #include <stdio.h>
- #include <opencv2/highgui/highgui.hpp>
- #include <opencv2/imgproc/imgproc.hpp>
- #include <opencv2/core/core.hpp>
- #include <opencv2/objdetect/objdetect.hpp>
- #include <errno.h>
- #include <string>
- using std::string;
- #include <iostream>
- #include <vector>
- #include <sstream>
- using std::stringstream;
- using namespace cv;
- using namespace std;
- int ydi_absname(char *buf, uint bufsiz)
- {
- int count = readlink( "/proc/self/exe", buf, bufsiz-1 );
- if (-1 == count)
- return -errno;
-
- buf[ count ] = '\0';
- return count;
- }
- int ydi_dirname(char *buf, uint bufsiz)
- {
- int count = ydi_absname(buf, bufsiz);
- if (count > 0) {
- do {
- if (buf[ --count ] == '/') {
- buf[ count ] = '\0';
- break;
- }
- } while (count > 0);
- }
- return count;
- }
- static Mat frame;
- static CascadeClassifier cascade, nestedCascade;
- static double scale = 4; //近距离用 4, 远用 6
- int detectAndDraw( Mat& img, CascadeClassifier& cascade, CascadeClassifier& nestedCascade, double scale)
- {
- int i = 0;
- double t = 0;
- //建立用于存放人脸的向量容器
- vector<Rect> faces, faces2;
- //定义一些颜色,用来标示不同的人脸
- //*
- const static Scalar colors[] = { CV_RGB(0,0,255),
- CV_RGB(0,128,255),
- CV_RGB(0,255,255),
- CV_RGB(0,255,0),
- CV_RGB(255,128,0),
- CV_RGB(255,255,0),
- CV_RGB(255,0,0),
- CV_RGB(255,0,255)} ;
- //*/
-
- //建立缩小的图片,加快检测速度
- //nt cvRound (double value) 对一个double型的数进行四舍五入,并返回一个整型数!
- Mat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 );
- //转成灰度图像,Harr特征基于灰度图
- cvtColor( img, gray, CV_BGR2GRAY );
-
- //改变图像大小,使用双线性差值
- resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR );
- //变换后的图像进行直方图均值化处理
- equalizeHist( smallImg, smallImg );
- //程序开始和结束插入此函数获取时间,经过计算求得算法执行时间
- t = (double)cvGetTickCount();
- //检测人脸
- //detectMultiScale函数中smallImg表示的是要检测的输入图像为smallImg,faces表示检测到的人脸目标序列,1.1表示
- //每次图像尺寸减小的比例为1.1,2表示每一个目标至少要被检测到3次才算是真的目标(因为周围的像素和不同的窗口大
- //小都可以检测到人脸),CV_HAAR_SCALE_IMAGE表示不是缩放分类器来检测,而是缩放图像,Size(30, 30)为目标的
- //最小最大尺寸
- cascade.detectMultiScale( smallImg, faces,
- 1.1, 2, 0
- //|CV_HAAR_FIND_BIGGEST_OBJECT
- //|CV_HAAR_DO_ROUGH_SEARCH
- |CV_HAAR_SCALE_IMAGE
- ,
- Size(30, 30));
- Mat smallImgROI;
- vector<Rect> nestedObjects;
- Point center;
- int radius;
-
- for( vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++)
- {
- Scalar color = colors[i%8];
- rectangle(img, cvPoint(cvRound(r->x*scale), cvRound(r->y*scale)), cvPoint(cvRound((r->x + r->width-1)*scale), cvRound((r->y + r->height -1)*scale)), color, 3, 8, 0);
- #if 0
- if (nestedCascade.empty()) {
- continue;
- }
-
- smallImgROI = smallImg(*r);
- nestedCascade.detectMultiScale(smallImgROI, nestedObjects, 1.1,2,0|CV_HAAR_SCALE_IMAGE, Size(30, 30));
-
- for (vector<Rect>::const_iterator nr=nestedObjects.begin(); nr != nestedObjects.end(); nr++)
- {
- center.x = cvRound((r->x + nr->x + nr->width*0.5)*scale);
- center.y = cvRound((r->y + nr->y + nr->height*0.5)*scale);
- radius = cvRound((nr->width + nr->height)*0.25*scale);
- circle(img, center, radius, color, 3,8,0);
- }
- #endif
-
- }
- return faces.size();
- }
- gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
- {
- return FALSE; //FALSE --> terminated application.
- }
- void destroy(GtkWidget *widget, gpointer data)
- {
- gtk_main_quit();
- }
- static GtkWidget *window, *vbox, *drawingarea;
- static gboolean on_draw_expose(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
- {
- if (frame.total() == 640 * 480) {
- cvtColor(frame, frame, CV_BGR2RGB, 3);
- gdk_draw_rgb_image(widget->window, widget->style->fg_gc[GTK_STATE_NORMAL], 0, 0, 640, 480, GDK_RGB_DITHER_MAX, frame.data, 640*3);
- }
- return 1;
- }
- static void gtk_window_init(int argc, char **argv)
- {
- gdk_threads_init();
-
- gtk_disable_setlocale();
- gtk_init(&argc, &argv);
-
- //windows
- window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- gtk_window_set_title(GTK_WINDOW(window), "USB Camera");
- gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
- gtk_window_set_default_size(GTK_WINDOW(window), 640,480);
- g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(delete_event), NULL);
-
- //vbox
- vbox = gtk_vbox_new(FALSE, 0);
- gtk_container_add(GTK_CONTAINER(window), vbox);
-
- //drawing area init
- drawingarea = gtk_drawing_area_new();
- gtk_box_pack_start(GTK_BOX(vbox), drawingarea, TRUE, TRUE, 0);
- gtk_drawing_area_size(GTK_DRAWING_AREA(drawingarea), 640,480);
- g_signal_connect(GTK_OBJECT(drawingarea), "expose-event", GTK_SIGNAL_FUNC(on_draw_expose), NULL);
-
- gtk_widget_show(vbox);
- gtk_widget_show(drawingarea);
- gtk_widget_show(window);
- }
- static void draw_thread(GtkWidget *widget)
- {
- VideoCapture cap(0);
- if (!cap.isOpened()) {
- printf("camera open failed.\n");
- return;
- }
-
- for (;;) {
- g_usleep(10000);
- cap >> frame;
- detectAndDraw(frame, cascade, nestedCascade, scale);
- gdk_threads_enter();
- gtk_widget_queue_draw(GTK_WIDGET(widget)); //触发 expose event
- gdk_threads_leave();
- }
- }
- int main(int argc, char **argv)
- {
- char l_dir[128];
- ydi_dirname(l_dir, sizeof(l_dir));
-
- string local_dir(l_dir) ;
- string cascadeName = local_dir + "/modules/haarcascade_frontalface_alt.xml";
- if( !cascade.load( cascadeName ) ) {
- cout << "ERROR: Could not load classifier cascade" << endl;
- return -1;
- }
-
- string nestedcascadeName = local_dir + "/modules/haarcascade_eye_tree_eyeglasses.xml";
- if( !nestedCascade.load( nestedcascadeName ) ) {
- cout << "ERROR: Could not load classifier nestedCascade" << endl;
- return -1;
- }
- gtk_window_init(argc, argv);
-
- GError* error = NULL;
- (void)g_thread_create((GThreadFunc)draw_thread, drawingarea, FALSE, &error);
-
- gdk_threads_enter();
- gtk_main();
- gdk_threads_leave();
- return 0;
- }