我正在运行一个OpenCV应用程序,该应用程序还使用其他外部库,例如Poco库,jsoncpp和SDL。
所有库都已在本地编译,我正在通过Makefile链接它们。
该程序从网络摄像头流式传输视频,并应捕获键盘输入(例如a
字符)以执行某项操作。
所有内容都在Ubuntu 18.04下; C ++源代码是正确的,因为在OSX下它可以毫无问题地运行,并且可以按预期进行操作(如果需要,我将附上源代码示例)。
程序运行并且没有停止,但是没有捕获键盘输入,并且一旦启动我就收到错误
(process:11477): GStreamer-CRITICAL **: 18:44:25.567: gst_element_get_state: assertion 'GST_IS_ELEMENT (element)' failed
OpenCV | GStreamer warning: GStreamer: unable to query pipeline state (/home/fra/Documents/openCV/openCV/modules/videoio/src/cap_gstreamer.cpp:420)
我已经安装了gstreamer库,因为它们是opencv所必需的,并且我将它们包括并链接到Makefile中,如下所示(请参阅完整的Makefile):
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-1.0.pc`\
...
和
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-1.0.pc`\
....
有人遇到过同样的问题吗?是什么产生异常?
我认为该错误与Opencv依赖关系有关,但不确定与SDL2.0有关不是问题。
C ++程序的源代码
这是一个最小的工作示例:在按下和释放键盘按钮时,单击鼠标的左右按钮有效(直接用Opencv回调捕获),这不会调用正确的SDL回调。
可以使用./executable camID anyNameYouWant
启动脚本,其中camID
是一个整数(通常为0或1),用于标识要使用的凸轮。
#ifndef __OPENCV__
#define __OPENCV__
#include "opencv2/opencv.hpp"
#endif
#include<iostream>
//#include "utils.hpp"
//#include "constants.hpp"
#include<unistd.h>
#include <vector>
#include<SDL.h>
#include <SDL_events.h>
using namespace cv;
using namespace std;
static const int delay = 2;
#define WINDOW_SCALE 1.7
//const int SCREEN_WIDTH = 640;
//const int SCREEN_HEIGHT = 480;
void onTrackbar_changed(int, void* data);
//void onThreshold_changed(int, void* data);
void onMouse(int evt, int x, int y, int flags, void* param);
void PrintKeyInfo( SDL_KeyboardEvent *key );
int keyboardCallback(SDL_KeyboardEvent ev);
//InputStateContext context;
int main(int argc, char* argv[])
{
/* Initialise SDL */
if( SDL_Init( SDL_INIT_VIDEO ) < 0)
{
fprintf( stderr, "Could not initialise SDL: %s\n", SDL_GetError() );
exit( -1 );
}
string host;
unsigned int port;
const String sourceReference = argv[1];
int camNum;
string sensorName;
try
{
camNum = stoi(sourceReference); // throws std::length_error
}
catch (const std::exception& e)// reference to the base of a polymorphic object
{
std::cout<<"Exception: " << e.what()<<endl; // information from length_error printed
return -1;
}
if (argc>4)
{
try
{
host = argv[2];
port = atoi(argv[3]);
sensorName = argv[4];
}
catch (const std::exception& e)
{
cout<<"impossible to convert host or port"<<endl;
return -1;
}
}
else if(argc>2)
{
cout<<"argumetns less than 4"<<endl;
host = "http://localhost";
port = 3456;
sensorName = argv[2];
cout<<argc<<endl;
cout<<"sensor name set from arguments: "<< sensorName<<endl;
}
else
{
cout<<"stopping execution: too few arguments."<<endl;
return -1;
}
VideoCapture cam(camNum);
/* or
VideoCapture captUndTst;
captUndTst.open(sourceCompareWith);*/
if ( !cam.isOpened())
{
cout << "Could not open reference " << sourceReference << endl;
return -1;
}
namedWindow("Camera", WINDOW_NORMAL);
Mat frame;
SDL_Event keyboardEvent;
cam>>frame;
resize(frame, frame, cv::Size(frame.cols/WINDOW_SCALE, frame.rows/WINDOW_SCALE));
resizeWindow("Camera", cv::Size(frame.cols/WINDOW_SCALE, frame.rows/WINDOW_SCALE));
setMouseCallback("Camera", onMouse, &frame);
while(1)
{
while( SDL_PollEvent( &keyboardEvent) )
{
switch( keyboardEvent.type )
{
/* Keyboard event */
/* Pass the event data onto PrintKeyInfo() */
case SDL_KEYDOWN:
break;
case SDL_KEYUP:
keyboardCallback(keyboardEvent.key);
break;
/* SDL_QUIT event (window close) */
case SDL_QUIT:
return 0;
break;
default:
break;
}
}
Mat frame_out;
frame_out = frame.clone();
cam>>frame;
resize(frame_out, frame_out, cv::Size(frame.cols/WINDOW_SCALE, frame.rows/WINDOW_SCALE));
imshow("Camera", frame_out);
/* A delay is needed to show (it actually wait for an input)*/
if(waitKey(delay)>delay){;}
}
return 0;
}
void onMouse(int evt, int x, int y, int flags, void* param)
{
if(evt == EVENT_LBUTTONDOWN)
{
cout<<"Left button pressed"<<endl;
}
else if(evt == EVENT_RBUTTONDOWN)
{
cout<<"Right button pressed"<<endl;
}
}
int keyboardCallback(SDL_KeyboardEvent ev)
{
switch(ev.keysym.sym)
{
case(SDLK_a):
cout<<"calling context keyboardA"<<endl;
break;
case(SDLK_e):
cout<<"calling context keyboardE"<<endl;
break;
case(SDLK_m):
cout<<"calling context keyboardM"<<endl;
break;
case SDLK_UP:
case SDLK_RIGHT:
cout<<"calling context RIGHT ARROW"<<endl;
break;
case SDLK_DOWN:
case SDLK_LEFT:
cout<<"calling context RIGHT ARROW"<<endl;
break;
case (SDLK_RETURN):
cout<<"calling context RIGHT ARROW"<<endl;
break;
default:
break;
}
return 0;
}
** COMPILATION **
要编译脚本,请使用以下Makefile
。库的路径是相对的(gstreamer库除外),因为我将它们构建在本地文件夹中。
CXX = g++
CXXFLAGS = -std=c++11
INC_PATH = `pkg-config --cflags ../openCV/build/lib/pkgconfig/opencv.pc` \
`pkg-config --cflags ../SDL2-2.0.8/instDir/lib/pkgconfig/sdl2.pc` \
`pkg-config --cflags ../jsoncpp/build/pkg-config/jsoncpp.pc` \
-I ../poco/instDir/include/ \
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-1.0.pc`\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-allocators-1.0.pc`\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-app-1.0.pc `\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-audio-1.0.pc `\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-bad-audio-1.0.pc `\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-bad-video-1.0.pc `\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-base-1.0.pc `\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-check-1.0.pc `\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-codecparsers-1.0.pc `\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-controller-1.0.pc `\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-fft-1.0.pc `\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-gl-1.0.pc `\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-insertbin-1.0.pc `\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-mpegts-1.0.pc `\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-net-1.0.pc `\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-pbutils-1.0.pc `\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-player-1.0.pc `\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-plugins-bad-1.0.pc `\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-plugins-base-1.0.pc `\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-plugins-good-1.0.pc `\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-riff-1.0.pc `\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-rtp-1.0.pc `\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-rtsp-1.0.pc `\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-sdp-1.0.pc`\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-tag-1.0.pc`\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-video-1.0.pc `\
`pkg-config --cflags /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-webrtc-1.0.pc`
#LIB_PATH = -L../cmake_bin_dir/lib/ ./gainput/build/lib -L../SDL2-2.0.8/build/ -L../SDL2-2.0.8/build/lib
LIBS = `pkg-config --libs ../openCV/build//lib/pkgconfig/opencv.pc` \
`pkg-config --libs ../SDL2-2.0.8/instDir/lib/pkgconfig/sdl2.pc` \
`pkg-config --libs ../jsoncpp/build/pkg-config/jsoncpp.pc` \
-L../poco/instDir/lib/ -lPocoNetd -lPocoUtild -lPocoFoundationd \
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-1.0.pc`\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-allocators-1.0.pc`\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-app-1.0.pc `\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-audio-1.0.pc `\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-bad-audio-1.0.pc `\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-bad-video-1.0.pc `\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-base-1.0.pc `\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-check-1.0.pc `\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-codecparsers-1.0.pc `\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-controller-1.0.pc `\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-fft-1.0.pc `\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-gl-1.0.pc `\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-insertbin-1.0.pc `\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-mpegts-1.0.pc `\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-net-1.0.pc `\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-pbutils-1.0.pc `\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-player-1.0.pc `\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-plugins-bad-1.0.pc `\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-plugins-base-1.0.pc `\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-plugins-good-1.0.pc `\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-riff-1.0.pc `\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-rtp-1.0.pc `\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-rtsp-1.0.pc `\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-sdp-1.0.pc`\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-tag-1.0.pc`\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-video-1.0.pc `\
`pkg-config --libs /usr/lib/x86_64-linux-gnu/pkgconfig/gstreamer-webrtc-1.0.pc`
SOURCEDIR := ./
SOURCES := $(wildcard $(SOURCEDIR)/*.cpp)
OBJDIR=$(SOURCEDIR)/obj
OBJECTS := $(patsubst $(SOURCEDIR)/%.cpp,$(OBJDIR)/%.o,$(SOURCES))
DEPENDS := $(patsubst $(SOURCEDIR)/%.cpp,$(OBJDIR)/%.d,$(SOURCES))
# ADD MORE WARNINGS!
WARNING := -Wall -Wextra
# .PHONY means these rules get executed even if
# files of those names exist.
.PHONY: all clean
# The first rule is the default, ie. "make",
# "make all" and "make parking" mean the same
all: parking
clean:
$(RM) $(OBJECTS) $(DEPENDS) parking
# Linking the executable from the object files
parking: $(OBJECTS)
$(CXX) $(WARNING) $(CXXFLAGS) $(INC_PATH) $^ -o $@ $(LIBS)
-include $(DEPENDS)
$(OBJDIR):
mkdir -p $(OBJDIR)
$(OBJDIR)/%.o: $(SOURCEDIR)/%.cpp Makefile $(OBJDIR)
$(CXX) $(WARNING) $(CXXFLAGS) $(INC_PATH) -MMD -MP -c $< -o $@