23,118
社区成员
发帖
与我相关
我的任务
分享
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
Mat frame;
Mat keyBoardInput = imread("keyboard_input.png",1);
Mat menu = imread("menu.png",1);
VideoCapture cap(0);
struct Para
{
Mat captureImage;
char keyInput;
char winName[3];
};
pthread_mutex_t dispwindow;
void *GUI_Thread(void * param)
{
//Mat keyBoardInput = imread("keyboard_input.png",1);
Para *p_data = (Para *)param;
while(p_data->captureImage.rows>0 && p_data->captureImage.cols>0)
{
pthread_mutex_lock (&dispwindow);
imshow("ppp",p_data->captureImage);
int key_input=cv::waitKey(30)%256;
if(key_input == 'q' || key_input == 'Q' )
{
p_data->keyInput = key_input;
break;
}
else if(key_input == 'd' || key_input == 'D' || key_input == 'L' || key_input == 'l'
|| key_input == 13 || key_input == 43)//13 enter; 43 +;
{
p_data->keyInput = key_input;
}
pthread_mutex_unlock (&dispwindow);
}
printf("GUI_Thread exited.\n");
pthread_exit(0);
return NULL;
}
void * Capture_Display_Thread(void * param)
{
Para *p_data = (Para *)param;
char key_input;
long exit_code = 0;
// VideoCapture cap(0);
if(!cap.isOpened()) // check if we succeeded
{
exit_code = -2;
}
//pthread_mutex_lock (&dispwindow);
while( p_data->keyInput != 'q' && p_data->keyInput != 'Q')
{
printf("\n displaying Video\n");
cap >> frame; // get a new frame from camera
if((frame.rows > 0) && (frame.cols > 0))
{
pthread_mutex_lock (&dispwindow);
Mat disp = frame.clone();
if(p_data->keyInput == 'd' || p_data->keyInput == 'D')
{
for(int i=100;i<200;i++)
{
for(int j=100;j<200;j++)
{
disp.at<Vec3b>(i,j)[0] = 255;
disp.at<Vec3b>(i,j)[1] = 255;
disp.at<Vec3b>(i,j)[2] = 255;
}
}
}
if(p_data->keyInput == 'l' ||p_data->keyInput == 'L')
{
//Mat menu = imread("menu.png",1);
menu.copyTo(disp(Rect(30,30,menu.cols,menu.rows)));
}
p_data->captureImage = disp.clone();
cv::imshow("ppp", disp);
pthread_mutex_unlock (&dispwindow);
}
waitKey(30);
}
//pthread_mutex_unlock (&dispwindow);
printf("stopped.\n");
pthread_exit((void *)exit_code);
return NULL;
}
int main(int argc, char * argv[])
{
Para mydata;
pthread_t display,gui;
void * exit_disp = NULL;
void * exit_gui = NULL;
pthread_mutex_init(&dispwindow, NULL);
printf("start...\n");
int rc = pthread_create(&gui, NULL, GUI_Thread, (void *)&mydata);
rc = pthread_create(&display, NULL, Capture_Display_Thread, (void *)&mydata);
if(0 != rc) return -1;
pthread_join(display, &exit_disp);
pthread_join(gui, &exit_gui);
// printf("gui = %c\n", mydata);
pthread_mutex_destroy(&dispwindow);
return 0;
}
// 创建GUI窗口
GtkWidget * create_main_window()
{
GtkWidget * window;
GtkWidget * vbox;
GtkWidget * table, * draw_area, * hruler, * vruler;
GtkWidget * hbox;
GtkWidget * button;
GtkWidget * separator;
GtkWidget * toggle, * checkbox;
GSList * group;
GtkWidget * radio;
GtkWidget * hscale;
// create toplevel window
gui.window = window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Video Capture");
g_signal_connect(window, "destroy", G_CALLBACK(on_destroy), NULL);
g_signal_connect(window, "delete-event", G_CALLBACK(on_quit_main), NULL);
gtk_widget_set_size_request(window, 800, 600);
// create a v-direction layout containter
gui.vbox = vbox = gtk_vbox_new(FALSE, 5);
gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
// create drawing area (with ruler)
table = gtk_table_new(3, 2, FALSE);
gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 5);
gui.draw_area = draw_area = gtk_drawing_area_new();
gui.image = gtk_image_new();
//~ gtk_widget_set_size_request(gui.image, 480, 320);
//~ gtk_widget_set_size_request(draw_area, 600, 400);
//~
//~ gtk_container_set_border_width(GTK_CONTAINER(draw_area), 20);
//~ gtk_container_add(GTK_CONTAINER(draw_area), gui.image);
hbox = gtk_hbox_new(TRUE, 2);
gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 1, 2, (GTK_EXPAND|GTK_FILL), GTK_FILL, 0, 0);
gtk_box_pack_start(GTK_BOX(hbox), gui.image, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(hbox), draw_area, FALSE, TRUE, 0);
gtk_widget_set_events(draw_area, GDK_POINTER_MOTION_MASK|GDK_POINTER_MOTION_HINT_MASK);
//~ g_signal_connect(draw_area, "expose_event", G_CALLBACK(on_expose_event), NULL);
hruler = gtk_hruler_new();
gtk_ruler_set_metric(GTK_RULER(hruler), GTK_PIXELS);
gtk_ruler_set_range(GTK_RULER(hruler), 0.0, 300.0, 0.0, 20.0);
g_signal_connect_swapped(draw_area, "motion_notify_event",
G_CALLBACK(GTK_WIDGET_GET_CLASS(hruler)->motion_notify_event), hruler);
gtk_table_attach(GTK_TABLE(table), hruler, 1, 2, 0, 1, (GTK_EXPAND|GTK_SHRINK|GTK_FILL), GTK_FILL, 0, 0);
separator = gtk_hseparator_new();
gtk_box_pack_start(GTK_BOX(vbox), separator, FALSE, TRUE, 5);
vruler = gtk_vruler_new();
gtk_ruler_set_metric(GTK_RULER(vruler), GTK_PIXELS);
gtk_ruler_set_range(GTK_RULER(vruler), 0.0, 200, 0.0, 200.0);
g_signal_connect_swapped(draw_area, "motion_notify_event",
G_CALLBACK(GTK_WIDGET_GET_CLASS(vruler)->motion_notify_event), vruler);
gtk_table_attach(GTK_TABLE(table), vruler, 0, 1, 1, 2, GTK_FILL, (GTK_EXPAND|GTK_SHRINK|GTK_FILL), 0, 0);
//~ separator = gtk_hseparator_new();
//~ gtk_box_pack_start(GTK_BOX(vbox), separator, FALSE, TRUE, 5);
// create a h-direction layout container and pack onto bottom
hbox = gtk_hbox_new(FALSE, 5);
gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
// create a toggle button to switch the display type from 'static-image' to 'capture'
gui.toggle = toggle = gtk_toggle_button_new_with_mnemonic("_Cap");
g_signal_connect(toggle, "toggled", G_CALLBACK(toggle_callback), GUINT_TO_POINTER(FLAG_CAPTURE));
gtk_box_pack_start(GTK_BOX(hbox), toggle, FALSE, FALSE, 0);
separator = gtk_vseparator_new();
gtk_box_pack_start(GTK_BOX(hbox), separator, FALSE, TRUE, 5);
// create a check box to show/hide logview output
checkbox = gtk_check_button_new_with_mnemonic("Show _log window");
g_signal_connect(checkbox, "toggled", G_CALLBACK(toggle_callback), GUINT_TO_POINTER(FLAG_LOGVIEW));
gtk_box_pack_start(GTK_BOX(hbox), checkbox, FALSE, FALSE, 5);
separator = gtk_vseparator_new();
gtk_box_pack_start(GTK_BOX(hbox), separator, FALSE, TRUE, 5);
// create some radio buttons to switch mode
radio = gtk_radio_button_new_with_mnemonic(NULL, "mode _0");
g_signal_connect(radio, "toggled", G_CALLBACK(on_radio_toggled), GINT_TO_POINTER(0));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE);
group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio));
gtk_box_pack_start(GTK_BOX(hbox), radio, FALSE, TRUE, 0);
radio = gtk_radio_button_new_with_mnemonic(group, "mode _1");
group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio));
g_signal_connect(radio, "toggled", G_CALLBACK(on_radio_toggled), GINT_TO_POINTER(1));
gtk_box_pack_start(GTK_BOX(hbox), radio, FALSE, TRUE, 0);
radio = gtk_radio_button_new_with_mnemonic(group, "mode _2");
g_signal_connect(radio, "toggled", G_CALLBACK(on_radio_toggled), GINT_TO_POINTER(2));
gtk_box_pack_start(GTK_BOX(hbox), radio, FALSE, TRUE, 0);
separator = gtk_vseparator_new();
gtk_box_pack_start(GTK_BOX(hbox), separator, FALSE, TRUE, 0);
// create some normal buttons to do something
button = gtk_button_new_with_mnemonic("_Open");
gtk_widget_set_size_request(button, 80, 20);
gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
g_signal_connect(button, "clicked", G_CALLBACK(on_button_clicked), GINT_TO_POINTER(1));
button = gtk_button_new_with_mnemonic("_Color");
gtk_widget_set_size_request(button, 80, 20);
gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5);
g_signal_connect(button, "clicked", G_CALLBACK(on_button_clicked), GINT_TO_POINTER(2));
separator = gtk_vseparator_new();
gtk_box_pack_start(GTK_BOX(hbox), separator, FALSE, TRUE, 0);
// create a 'quit' button to exit
button = gtk_button_new_with_label("quit");
gtk_widget_set_size_request(button, 80, 20);
gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, TRUE, 0);
g_signal_connect_swapped(button, "clicked", G_CALLBACK(gtk_widget_destroy), (gpointer)window);
// create a h-direction layout container and pack onto bottom
hbox = gtk_hbox_new(FALSE, 5);
gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
// creat a trackbar (range widget)
GtkObject * adjust = gtk_adjustment_new(0.0, 0.0, 110.0, 0.5, 5.0, 10.0);
gui.hscale = hscale = gtk_hscale_new(GTK_ADJUSTMENT(adjust));
gtk_widget_set_size_request(hscale, 200, -1);
gtk_range_set_update_policy(GTK_RANGE(hscale), GTK_UPDATE_CONTINUOUS);
gtk_scale_set_digits(GTK_SCALE(hscale), 1);
gtk_scale_set_value_pos(GTK_SCALE(hscale), GTK_POS_TOP);
gtk_scale_set_draw_value(GTK_SCALE(hscale), TRUE);
gtk_box_pack_start(GTK_BOX(hbox), hscale, TRUE, TRUE, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
gtk_widget_show_all(window);
return window;
}
// toggle and check button的回调函数
void toggle_callback(GtkWidget * widget, gpointer data)
{
guint flag = GPOINTER_TO_UINT(data);
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
{
gui.uflags |= flag;
}else
{
gui.uflags &= ~flag;
}
if(flag < FLAG_LOGVIEW)
{
// signal was sent by the toggle button
if(gui.uflags & FLAG_CAPTURE)
{
g_print("display capture ...\n");
StartCapture();
}else
{
StopCapture();
g_print("display static image ...\n");
}
}
else
{
// signal was sent by the checkbox
if(gui.uflags & FLAG_LOGVIEW)
{
g_print("show logview...\n");
}else
{
g_print("hide logview...\n");
}
}
}
// radio按钮的回调函数
void on_radio_toggled(GtkWidget * widget, gpointer data)
{
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
{
gui.mode = GPOINTER_TO_INT(data);
switch(gui.mode)
{
case 0:
// do sth.
break;
case 1: // do sth.
break;
case 2: // do sth.
break;
default:
return;
}
g_print("mode = %d\n", gui.mode);
}
}
// 当在"色彩选择器"对话框中选取了某一颜色时, 更改右侧绘图区的背景
static void on_color_changed(GtkWidget * widget, GtkColorSelection * color_sel)
{
GdkColor color;
gtk_color_selection_get_current_color(color_sel, &color);
gtk_widget_modify_bg(gui.draw_area, GTK_STATE_NORMAL, &color);
}
// 点击按钮时, 做相应的处理
void on_button_clicked(GtkWidget * widget, gpointer data)
{
gint id = GPOINTER_TO_INT(data);
int rc;
if(1 == id) // button 1 clicked
{
// do sth.
}else if(2 == id) // button 2 clicked
{
// 点击button2 按钮时, 打开色彩选择器对话框
GtkColorSelection * color_sel;
GtkWidget * dlg;
dlg = gtk_color_selection_dialog_new("Change color");
color_sel = GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(dlg)->colorsel);
gtk_color_selection_set_previous_color(color_sel, &gui.color);
gtk_color_selection_set_current_color(color_sel, &gui.color);
gtk_color_selection_set_has_palette(color_sel, TRUE);
g_signal_connect(color_sel, "color_changed", G_CALLBACK(on_color_changed), (gpointer)color_sel);
rc = gtk_dialog_run(GTK_DIALOG(dlg));
if(GTK_RESPONSE_OK == rc)
{
gtk_color_selection_get_current_color(color_sel, &gui.color);
}else
{
gtk_widget_modify_bg(gui.draw_area, GTK_STATE_NORMAL, &gui.color);
}
gtk_widget_destroy(dlg);
}
}
/*
* test3.c
*
* Copyright 2015 Che Hongwei <htc.chehw@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*
*/
#include <stdio.h>
#include <opencv/cv.h>
#include <opencv/cxcore.h>
#include <opencv/highgui.h>
//~ #include <opencv2/core/core_c.h>
//~ #include <opencv2/imgproc/imgproc_c.h>
//~ #include <opencv2/highgui/highgui_c.h>
#include <gtk/gtk.h>
typedef struct GUI_PARAM
{
GtkWidget * window;
GtkWidget * vbox;
GtkWidget * draw_area;
GtkWidget * toggle;
GtkWidget * logview;
GtkWidget * statusbar;
GtkWidget * hscale;
GdkColor color;
guint uflags;
gint mode;
gint timer;
gboolean running;
GtkWidget * image;
CvCapture * capture;
}GUI_PARAM_t;
GUI_PARAM_t gui;
enum GLOBAL_FLAGS
{
FLAG_STATIC_IMAGE = 0,
FLAG_CAPTURE = 1,
FLAG_LOGVIEW = 2
};
GtkWidget * create_main_window();
int main(int argc, char **argv)
{
gdk_threads_init();
gtk_init(&argc, &argv);
create_main_window();
gtk_main();
return 0;
}
void toggle_callback(GtkWidget * widget, gpointer data);
void on_radio_toggled(GtkWidget * widget, gpointer data);
void on_button_clicked(GtkWidget * widget, gpointer data);
// 在timeout中读取从摄像头中捕获的图像,
// 根据需要进行加工处理后, 用Gtk的GtkImage部件来显示
static gboolean on_timeout(gpointer data)
{
// 界面左下角的切换按钮可以控制[启动]/[终止]捕获
if(NULL == gui.capture) { // 如果当前没启动捕获, 则不做任何处理
return TRUE;
}
IplImage * frame = cvQueryFrame(gui.capture); // 读取当前捕获到的帧
IplImage * output = NULL;
IplImage * temp;
GdkPixbuf * pix;
unsigned char * imageData = NULL;
if(NULL == frame)
{
g_printerr("cvQueryFrame failed.\n");
return TRUE;
}
switch(gui.mode) // 界面下方放了三个radio按钮, 用于切换显式效果
{
case 0: // 直接显式
// opencv默认的色彩方案是BGR模式, 在gtk的界面下显式则需要先转换为RGB模式
output = cvCreateImage(cvGetSize(frame), frame->depth, frame->nChannels);
if(NULL != output)
{
cvCvtColor(frame, output, CV_BGR2RGB);
}
break;
case 1: // 转换为灰度图
temp = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 1);
output = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 3);
//~ memset(output, 0, sizeof(IplImage));
cvCvtColor(frame, temp, CV_BGR2GRAY);
cvCvtColor(temp, output, CV_GRAY2RGB);
cvReleaseImage(&temp);
break;
case 2: // 模糊(柔化)处理
// opencv-2.4.9可能有bug, 在C下直接用 cvCreateImage / cvSmooth后,无法回收内存:
// 一旦调用cvReleaseImage,就会出现Segmentation fault
// 有可能是在某些函数内部被opencv库用c++的new分配了内存, 而釋放時可能用的是free
// 目前的解决方法是:
// 用malloc为imageData分配内存, 然后调用 cvCreateImageHeader + cvSetData 来替代 cvCreateImage
imageData = (unsigned char *)malloc(frame->widthStep * frame->height * frame->nChannels);
temp = cvCreateImageHeader(cvGetSize(frame), IPL_DEPTH_8U, 3);
cvSetData(temp, imageData, frame->widthStep * frame->nChannels);
output = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 3);
cvSmooth(frame, temp, CV_GAUSSIAN, 3, 3, 0.0, 0.0);
cvCvtColor(temp, output, CV_BGR2RGB);
cvReleaseImageHeader(&temp);
free(imageData);
break;
}
if(NULL != output)
{
// 将图像的数据转换为GdkPix格式, 并在GtkImage控件中显示
pix = gdk_pixbuf_new_from_data((const guchar *)output->imageData,
GDK_COLORSPACE_RGB, FALSE,
output->depth, output->width, output->height,
output->widthStep,
NULL, NULL);
cvReleaseImage(&output);
gtk_image_set_from_pixbuf(GTK_IMAGE(gui.image), pix);
g_object_unref(pix);
gtk_widget_queue_draw(gui.image);
}
return TRUE;
}
static void StartCapture()
{
if(NULL == gui.capture)
{
gui.capture = cvCreateCameraCapture(0);
//~ gui.capture = cvCaptureFromCAM(0);
if(NULL == gui.capture)
{
perror("cvCreateCameraCapture failed.\n");
return;
}
}
if(!gui.running) // 如果定时器没启动
{
// 设置定时器, 大约每33毫秒读取一帧(30fps)
gui.timer = g_timeout_add(33, (GSourceFunc)on_timeout, NULL);
gui.running = TRUE;
}
}
static void StopCapture()
{
if(gui.running)
{
gtk_timeout_remove(gui.timer);
gui.running = FALSE;
}
}
static gboolean on_quit_main(GtkWidget * widget, GdkEvent * event, gpointer data)
{
StopCapture();
if(NULL != gui.capture)
{
cvReleaseCapture(&gui.capture);
gui.capture = NULL;
}
gtk_main_quit();
return FALSE;
}
static void on_destroy(GtkWidget * widget, gpointer data)
{
StopCapture();
if(NULL != gui.capture)
{
cvReleaseCapture(&gui.capture);
gui.capture = NULL;
}
gtk_main_quit();
}
// 一层写不下,后面还有...
#include <stdio.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <opencv/cxcore.h>
const char * cap_winname = "Capture Window";
//~ const char * result_winname = "Result Window";
int display_capture(const char * window_name)
{
int ret = -1;
CvCapture * capture = cvCreateCameraCapture(0);
if(NULL == capture) return ret;
IplImage * frame;
IplImage * menu = cvLoadImage("menu.png", CV_LOAD_IMAGE_COLOR);
char cmd;
char flags = 0;
while(1)
{
frame = cvQueryFrame(capture);
if(NULL == frame) break;
IplImage * output;
cmd = cvWaitKey(33);
switch(cmd)
{
case 'q': case 'Q': // 按‘q’键退出
ret = 0;
goto label_quit;
case 'l': case 'L': //显示 menu.png
flags = 'l';
break;
case 'd': case 'D': // 对frame帧进行处理,比如smooth
flags = 'd';
break;
//default:
case 27: // 按'ESC'建返回默认状态
flags = 0;
break;
default:
break;
}
if(flags == 'l')
{
cvShowImage(window_name, menu);
}else if(flags == 'd')
{
output = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 3);
cvSmooth(frame, output, CV_GAUSSIAN, 3, 3, 0, 0);
cvShowImage(window_name, output);
cvReleaseImage(&output);
}else
cvShowImage(window_name, frame);
}
label_quit:
printf("quit\n");
cvReleaseImage(&menu);
cvReleaseCapture(&capture);
return ret;
}
int main(int argc, char **argv)
{
cvNamedWindow(cap_winname, CV_WINDOW_AUTOSIZE);
// cvNamedWindow(result_winname, CV_WINDOW_AUTOSIZE);
display_capture(cap_winname);
cvDestroyAllWindows();
return 0;
}
如果对opencv的底层实现有一定了解,完全可以不使用highgui,而是用自己熟悉的GUI库来显式经opencv处理后的图像(稍微有点儿复杂,就不写示例了)。