OpenCV / HighGUI draws new windows for each attached object - opencv

I'm working through Learning OpenCV 3 by Kaehler & Bradski.
I've applied all errata fixes to this code per http://www.oreilly.com/catalog/errata.csp?isbn=0636920044765.
Expected behavior: the trackbar should be attached to the namedWindow "Example2-4", then frames from a video file (specified via command-line argument) should be drawn in the same window.
Actual behavior: the trackbar is drawn in one window named "Example2-4", then the frames are drawn in a second window named "Example2-4". Closing either window causes the program to hang. Otherwise the behavior is correct.
Platform: Windows 10, x64, OpenCV 3.3
Edit 1:
I tried adding a string literal to the top of main():
char *window_name = "Window";
and replacing every instance of "Example2-4" with window_name. This didn't change the behavior.
Edit 2:
This code is the first time I've tried to add an interactive widget, but adding images and video frames to windows in previous examples also generated two windows with the same name. I suspect I'm up against a configuration issue, but I still have no idea how to solve it.
Edit 3: I've added code for the simplest program that will demonstrate the problem behavior, and changed the title of this post to characterize it better.
Code:
/* Windows precompiled headers */
//#include "stdafx.h"
/* C++ */
#include <iostream>
#include <fstream>
/* OpenCv */
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace std;
int g_slider_position = 0;
int g_run = 1, g_dontset = 0; // start out in single step mode
cv::VideoCapture g_cap;
void onTrackBarSlide(int pos, void *);
int main(int argc, char **argv)
{
cv::namedWindow("Example2-4", CV_WINDOW_AUTOSIZE);
g_cap.open(string(argv[1]));
int frames = (int)g_cap.get(CV_CAP_PROP_FRAME_COUNT);
int tmpw = (int)g_cap.get(CV_CAP_PROP_FRAME_WIDTH);
int tmph = (int)g_cap.get(CV_CAP_PROP_FRAME_HEIGHT);
cout << "Video has " << frames << " frames of dimensions ("
<< tmpw << ", " << tmph << ")." << endl;
cv::createTrackbar("Position", "Example2-4", &g_slider_position, frames,
onTrackBarSlide);
cv::Mat frame;
for (;;) {
if (g_run != 0) {
g_cap >> frame;
if (frame.empty())
break;
int current_pos = (int)g_cap.get(CV_CAP_PROP_POS_FRAMES);
g_dontset = 1;
cv::setTrackbarPos("Position", "Example2-4", current_pos);
cv::imshow("Example2-4", frame);
g_run -= 1;
}
char c = (char)cv::waitKey(10);
if (c == 's') { // single step
g_run = 1;
cout << "Single step, run = " << g_run << endl;
}
if (c == 'r') { // run mode
g_run = -1;
cout << "Run mode, run = " << g_run << endl;
}
if (c == 27)
break;
}
return 0;
}
void onTrackBarSlide(int pos, void *) {
g_cap.set(CV_CAP_PROP_POS_FRAMES, pos);
if (!g_dontset)
g_run = 1;
g_dontset = 0;
}
Simplest code which results in problem behavior. Gets an image via command line argument:
#include <opencv2\opencv.hpp>
int main(int argc, char **argv)
{
char *window_name = "Window";
cv::Mat img = cv::imread(argv[1], -1);
if (img.empty())
return -1;
cv::namedWindow(window_name, CV_WINDOW_AUTOSIZE);
cv::imshow(window_name, img);
cv::waitKey(0);
cv::destroyWindow(window_name);
return 0;
}

Related

IP camera keeps dropping frames

I am using an ethernet camera in opencv but I repeatedly get the following warning message when I run my program.
[rtp # 0x1a9c720] Received packet without a start chunk; dropping frame.
I think the problem might be with the rtp url I am using:
vcap.open("rtp://192.168.40.90:50004/");
I'm not even sure if I should be using rtp or something else.
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc, char *argv[])
{
VideoCapture vcap;
vcap.open("rtp://192.168.40.90:50004/"); // open IP cam
int numberOfFrames = 0;
for(;;)
{
Mat frame;
vcap >> frame;
cout << "number of frames = " << ++numberOfFrames << endl;
imshow( "display", frame );
char c = (char)waitKey(1);
if( c == 27 ) break;
}
vcap.release();
return 0;
}

How can I store a big matrix within the .cc file?

I am currently working on a Computer Vision / Machine Learning project for university. Sadly, they only allow us to upload one single file and restrict the computation time too much. Hence I need to compute the matrices on my machine and store them in the same file as the code (22500 rows, 1 col and 100 rows + 22500 col and 100 rows + 1 col). I already found a way to export the data (link), but I'm not sure how to initialize the matrix.
What I've tried
#include <opencv/cv.h>
#include <opencv/highgui.h>
int main(int argc, char const *argv[])
{
float data[10] = {1,2,3,4,5,7,8,9,10,11};
cv::Mat A;
// Something is wrong with this line
A = cv::Mat(1, 10, cv::CV_32FC1, data);
return 0;
}
When I compile it, I get:
main.cc: In function ‘int main(int, const char**)’:
main.cc:10:16: error: expected primary-expression before ‘(’ token
A = cv::Mat(1, 10, cv::CV_32FC1, data);
^
In file included from /usr/include/opencv2/core/core_c.h:47:0,
from /usr/include/opencv/cv.h:63,
from main.cc:1:
main.cc:10:28: error: expected unqualified-id before ‘(’ token
A = cv::Mat(1, 10, cv::CV_32FC1, data);
^
Second try
#include <opencv/cv.h>
#include <opencv/highgui.h>
int main(int argc, char const *argv[])
{
float dataHeaderMat1[10] = {1,2,3,4,5,7,8,9,10,11};
cv::Mat matrix1;
// Something is wrong with this line
cv::cvInitMatHeader( &matrix1, 10, 1, CV_64FC1, dataHeaderMat1);
return 0;
}
gives
main.cc:10:5: error: ‘cvInitMatHeader’ is not a member of ‘cv’
cv::cvInitMatHeader( &matrix1, 10, 1, CV_64FC1, dataHeaderMat1);
^
The following works to declare and initialize a matrix:
#include <opencv/cv.h>
#include <opencv/highgui.h>
int main(int argc, char const *argv[])
{
float data[10] = {1,2,3,4,5,7,8,9,10,11};
cv::Mat A;
// Something is wrong with this line
A = cv::Mat(1, 10, CV_32FC1, data);
return 0;
}
However, I'm not too sure if this is the best way for big arrays.
You can try to save image to header file, like this:
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
// uncomment for test
//#include "image.h"
int main(int argc, char **argv)
{
// This part creates header file from image.
Mat img=imread("D:\\ImagesForTest\\lena.jpg");
int w=img.cols;
int h=img.rows;
int channels=img.channels();
ofstream os("image.h");
os << "int rows=" << h << ";" << endl;
os << "int cols=" << w << ";" << endl;
os << "unsigned char d[]={" << endl;
for(int i=0;i<h;++i)
{
for(int j=0;j<w;++j)
{
if(i!=(w-1) || j!=(h-1))
{
Vec3b b=img.at<Vec3b>(i,j);
os << format("0x%02x,",b[0]);
os << format("0x%02x,",b[1]);
os << format("0x%02x,",b[2]);
}
}
}
Vec3b b=img.at<Vec3b>(w-1,h-1);
os << format("0x%02x,",b[0]);
os << format("0x%02x,",b[1]);
os << format("0x%02x",b[2]);
os << endl << "};" << endl;
os << "Mat I=Mat(rows,cols,CV_8UC3,d);" << endl;
os.close();
// To test uncomment commented part of code and comment uncommented.
// uncomment for test
/*
namedWindow("I");
imshow("I",I);
waitKey();
return 0;
*/
}
But be careful, not all IDEs likes such large files.

OpenCV 3.0 printing Mat

I am a newbie to OpenCV, so pls bear with me.. I am trying to dump the histogram Mat object for the given image.. It fails with the below error - Any help appreciated...
The first cout in the below program i.e of the loaded image prints successfully - While the second cout of the hist of the image fails with the below error
OpenCV Error: Assertion failed (m.dims <= 2) in FormattedImpl, file /mycode/ws/opencv/opencv-3.0.0-beta/modules/core/src/out.cpp, line 86
libc++abi.dylib: terminating with uncaught exception of type cv::Exception: /mycode/ws/opencv/opencv-3.0.0-beta/modules/core/src/out.cpp:86: error: (-215) m.dims <= 2 in function FormattedImpl
Here is the complete code
#include <stdio.h>
#include <string>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main(int argc, char** argv) {
if (argc != 2) {
printf("usage: opencv.out <Image_Path>\n");
return -1;
}
string imagePath = (argv[1]);
cout << "loading image..." << imagePath << endl;
Mat image = imread(imagePath, 1);
Mat hist;
int imgCount = 1;
int dims = 3;
const int histSizes[] = {4, 4, 4};
const int channels[] = {0, 1, 2};
float rRange[] = {0, 256};
float gRange[] = {0, 256};
float bRange[] = {0, 256};
const float *ranges[] = {rRange, gRange, bRange};
Mat mask = Mat();
calcHist(&image, imgCount, channels, mask, hist, dims, histSizes, ranges);
cout << image << "Loaded image..." << endl;
cout << "Hist of image..." << hist;
return 0;
}
Based on the OpenCV 2.4.9 source code:
static inline std::ostream& operator << (std::ostream& out, const Mat& mtx)
{
Formatter::get()->write(out, mtx);
return out;
}
Is the function you are calling when using << operator. Formatter::get() returns appropriate
formatter class based on the programming language you are using.
write() function basicly calls:
static void writeMat(std::ostream& out, const Mat& m, char rowsep, char elembrace, bool singleLine)
{
CV_Assert(m.dims <= 2);
int type = m.type();
char crowbrace = getCloseBrace(rowsep);
char orowbrace = crowbrace ? rowsep : '\0';
if( orowbrace || isspace(rowsep) )
rowsep = '\0';
for( int i = 0; i < m.rows; i++ )
{
if(orowbrace)
out << orowbrace;
if( m.data )
writeElems(out, m.ptr(i), m.cols, type, elembrace);
if(orowbrace)
out << crowbrace << (i+1 < m.rows ? ", " : "");
if(i+1 < m.rows)
{
if(rowsep)
out << rowsep << (singleLine ? " " : "");
if(!singleLine)
out << "\n ";
}
}
}
As you can see if your Mat dimensionality is greater than 2 assertion will be thrown like in your code (CV_Assert(m.dims<=2)).
calcHist() with the parameters you gave produces 3-dimentional Mat and thus it cannot be displayed using << operator
By calling calcHist() function that way you are getting 3-dimentional histogram and I don't see a simple solution to visualize that in OpenCV (which doesn't mean it can't be done). If it's something you must do I would suggest to look into OpenGL for 3D data visualization. If not you could simply call this function for each channel seperatly - you will get 3 one-dimenational histograms which you can print using << operator.

Grabbing Pixel data from a video strem

I am having trouble if understanding certain coding i am sorry if this comes off as stupid but i have a code to capture a video from my webcam i want to get the RGB valuee from the frame, if this is impossible would have to to save a frame as a picture and then get values from it?
const char window_name[]="Webcam";
int main(int argc, char* argv[])
{
/* attempt to capture from any connected device */
CvCapture *capture=cvCaptureFromCAM(CV_CAP_ANY);
if(!capture)
{
printf("Failed to initialise webcam\n");
return -1;
}
/* create the output window */
cvNamedWindow(window_name, CV_WINDOW_NORMAL);
do
{
/* attempt to grab a frame */
IplImage *frame=cvQueryFrame(capture);
if(!frame)
{
printf("Failed to get frame\n");
break;
}
COLORREF myColAbsolute = GetPixel(frame, 10,10);//error in saying frame is not compatible with HDC.
cout << "Red - " << (int)GetRValue(myColAbsolute) << endl;
cout << "Green - " << (int)GetGValue(myColAbsolute) << endl;
cout << "Blue - " << (int)GetBValue(myColAbsolute) << endl;
/* show the frame */
cvShowImage(window_name, frame);
ha ! ( obviously caught with a copy & paste bummer )
GetPixel() is a windows function, not an opencv one. same for GetRValue() and sisters.
you'd use them in the native win32 api, to get a pixel from an HDC, but it won't work with opencv/highgui, since neither HDC, nor HWND are exposed.
since you're obviously a beginner(nothing wrong with that, again!) let me try to talk you out of using the old, 1.0 opencv api(IplImages, cv*Functions) as well,
you should be using the new one(cv::Mat, namespace cv::Functions) instead.
#include "opencv2/opencv.hpp"
#include "opencv2/highgui/highgui.hpp"
using namespace cv;
using namespace std;
int main()
{
Mat frame;
namedWindow("video", 1);
VideoCapture cap(0);
while ( cap.isOpened() )
{
cap >> frame;
if(frame.empty()) break;
int x=3, y=5;
// Ladies and Gentlemen, the PIXEL!
Vec3b pixel = frame.at<Vec3b>(y,x); // row,col, not x,y!
cerr << "b:" << int(pixel[0]) << " g:" << int(pixel[1]) << " r:" << int(pixel[2]) << endl;
imshow("video", frame);
if(waitKey(30) >= 0) break;
}
return 0;
}

opencv cvblob -- render blobs other than white

I am trying to detect objects with cvblob. Somehow, my code only marks the white objects. How to mark objects of other colors, like a can of beer or a bottle of water.
Here is my code:
#include "highgui.h"
#include "cv.h"
#include "cvaux.h"
#include "iostream"
#include <stdio.h>
#include <ctype.h>
#include <cvblob.h>
using namespace cv;
using namespace std;
using namespace cvb;
int main(int argc, char** argv) {
CvTracks tracks;
cvNamedWindow("frame", CV_WINDOW_AUTOSIZE);
cvMoveWindow("frame", 50, 100);
CvCapture* capture;
IplImage* frame = 0;
capture = cvCreateCameraCapture( 0 ); //capture frames from cam on index 0: /dev/video0/
if (!capture) {
return -1;
}
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 320);
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 240);
frame = cvQueryFrame(capture);
while(frame) {
IplImage *gray = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 1);
cvCvtColor(frame, gray, CV_BGR2GRAY);
cvThreshold(gray, gray, 150, 255, CV_THRESH_BINARY);
IplImage *labelImg=cvCreateImage(cvGetSize(gray), IPL_DEPTH_LABEL, 1);
CvBlobs blobs;
unsigned int result=cvLabel(gray, labelImg, blobs);
cvFilterByArea(blobs, 500, 1000000);
// cvRenderBlobs(labelImg, blobs, frame, frame, CV_BLOB_RENDER_BOUNDING_BOX);
cvRenderBlobs(labelImg, blobs, frame, frame, CV_BLOB_RENDER_CENTROID);
cvUpdateTracks(blobs, tracks, 200., 5);
cvRenderTracks(tracks, frame, frame, CV_TRACK_RENDER_ID|CV_TRACK_RENDER_BOUNDING_BOX);
for (CvBlobs::const_iterator it=blobs.begin(); it!=blobs.end(); ++it) {
cout << "Blob #" << it->second->label << ": Area=" << it->second->area << ", Centroid=(" << it->second->centroid.x << ", " << it->second->centroid.y << ")" << endl;
}
cvShowImage("frame", frame);
cout << "----------------------------" << endl;
frame = cvQueryFrame(capture);
char c = cvWaitKey(10);
if(c==27)
break;
}
}
Any tip is appreciated.
Milo
That's the option by default and you cannot change it if you don't change the source code in cvblob library.
If you really want to change this is so easy, you can create a copy of the same method adding a new input var like CvScalar to select output color. It's so easy.
The method cvRenderBlob will be in cvcontour.cpp.
I've been made many improvement in cvblob library and in next months I will push it to the creator.
Try adding:
"cvInRangeS(hsvframe,cvScalar(23,41,133),cvScalar(40,150,255),threshy);//for yellow"
Before Filtering the blobs. Its a range of HSV(instead of RGB) values that defines the threshold of the desire color.
Hope it helps.

Resources