This will probably be a dumb question, but i really can't figure it out.
First of all: sorry for the vague title, i'm not really sure about how to describe my problem in a couple of words.
I'm using OpenCV 2.4.3 in MS Visual Studio, C++. I'm using the VideoCapture interface for capturing frames from my laptop webcam.
What my program should do is:
Loop on different poses of the user, for each pose:
wait that the user is in position (a getchar() waits for an input that says "i'm in position" by simply hitting enter)
read the current frame
extract a region of intrest from that frame
save the image in the ROI and then label it
Here is the code:
int main() {
Mat img, face_img, img_start;
Rect *face;
VideoCapture cam(0);
ofstream fout("dataset/dataset.txt");
if(!fout) {
cout<<"Cannot open dataset file! Aborting"<<endl;
return 1;
}
int count = 0; // Number of the (last + 1) image in the dataset
// Orientations are: 0°, +/- 30°, +/- 60°, +/-90°
// Distances are just two, for now
// So it is 7x2 images
cam.read(img_start);
IplImage image = img_start;
face = face_detector(image);
if(!face) {
cout<<"No face detected..? Aborting."<<endl;
return 2;
}
// Double ROI dimensions
face->x = face->x-face->width / 2;
face->y = face->y-face->height / 2;
face->width *= 2;
face->height *=2;
for(unsigned i=0;i<14;++i) {
// Wait for the user to get in position
getchar();
// Get the face ROI
cam.read(img);
face_img = Mat(img, *face);
// Save it
stringstream sstm;
string fname;
sstm << "dataset/image" << (count+i) << ".jpeg";
fname = sstm.str();
imwrite(fname,face_img);
//do some other things..
What i expect from it:
i stand in front of the camera when the program starts and it gets the ROI rectangle using the face_detector() function
when i'm ready, say in pose0, i hit enter and a picture is taken
from that picture a subimage is extracted and it is saved as image0.jpeg
loop this 7 times
What it does:
i stand in front of the camera when the program starts, nothing special here
i hit enter
the ROI is extracted not from the picture taken in that moment, but from the first one
At first, i used img in every cam.capture(), then i changed the first one in cam.capture(img_start) but that didn't help.
The second iteration of my code saves the image that should have been saved in the 1st, the 3rd iteration the one that should have been saved in the 2nd and so on.
I'm probably missing someting important from the VideoCapture, but i really can't figure it out, so here i am.
Thanks for any help, i really appreciate it.
The problem with your implementation is that the camera is not running freely and capturing images in real time. When you start up the camera, the videocapture buffer is filled up while waiting for you to read in the frames. Once the buffer is full, it doesn't drop old frames for new ones until you read and free up space in it.
The solution would be to have a separate capture thread, in addition to your "process" thread. The capture thread keeps reading in frames from the buffer whenever a new frame comes in and stores it in a "recent frame" image object. When the process thread needs the most recent frame (i.e. when you hit Enter), it locks a mutex for thread safety, copies the most recent frame into another object and frees the mutex so that the capture thread continues reading in new frames.
#include <iostream>
#include <stdio.h>
#include <thread>
#include <mutex>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace std;
using namespace cv;
void camCapture(VideoCapture cap, Mat* frame, bool* Capture){
while (*Capture==true) {
cap >> *frame;
}
cout << "camCapture finished\n";
return;
}
int main() {
VideoCapture cap(0); // open the default camera
if (!cap.isOpened()) // check if we succeeded
return -1;
Mat *frame, SFI, Input;
frame = new Mat;
bool *Capture = new bool;
*Capture = true;
//your capture thread has started
thread captureThread(camCapture, cap, frame, Capture);
mtx.lock();
imshow(*frame,current_frame);
mtx.unlock();
//Terminate the thread
mtx.lock();
*Capture = false;
mtx.unlock();
captureThread.join();
return 0;
}
This is the code that I wrote from the above advice. I hope someone can get help from this.
When you are capturing the image continuously, no captured frame will be stored in the opencv buffer, such that there will be no lag in streaming.
If you take screenshot/capture image with some time gap inbetween, the captured image will be first stored in the opencv buffer, after that the image is retrieved from the buffer.
When the buffer is full, when you are calling captureObject >> matObject, the last frame from the image is returned, not the current frame in the capturecard/webcam.
So only you are seeing a lag in your code. This issue can be resolved by taking screenshot based on the frames per second (fps) value of the webcam and time taken to capture the screenshot.
The time taken to read frame from buffer is very less, Measure the time taken to take the screenshot. If it is lesser than the fps we can assume that is read from buffer else it means it is captured from webcam.
Sample Code:
For capturing a recent screenshot from webcam.
#include <opencv2/opencv.hpp>
#include <time.h>
#include <thread>
#include <chrono>
using namespace std;
using namespace cv;
int main()
{
struct timespec start, end;
VideoCapture cap(-1); // first available webcam
Mat screenshot;
double diff = 1000;
double fps = ((double)cap.get(CV_CAP_PROP_FPS))/1000;
while (true)
{
clock_gettime(CLOCK_MONOTONIC, &start);
//camera.grab();
cap.grab();// can also use cin >> screenshot;
clock_gettime(CLOCK_MONOTONIC, &end);
diff = (end.tv_sec - start.tv_sec)*1e9;
diff = (diff + (end.tv_nsec - start.tv_nsec))*1e-9;
std::cout << "\n diff time " << diff << '\n';
if(diff > fps)
{
break;
}
}
cap >> screenshot; // gets recent frame, can also use cap.retrieve(screenshot);
// process(screenshot)
cap.release();
screenshot.release();
return 0;
}
Related
I wrote a simple OpenCV program that recovers my webcam video stream and display it on a simple window. I wante to resize this window to the resolution 256x256 but it changed it to 320x240.
Here's my source code :
#include <iostream>
#include <opencv/cv.h>
#include <opencv/highgui.h>
using namespace std;
int main(int argc, char** argv)
{
char key;
cvNamedWindow("Camera_Output", cv::WINDOW_NORMAL);
CvCapture *capture = cvCaptureFromCAM(CV_CAP_ANY);
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 256);
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 256);
while(1){
IplImage *frame = cvQueryFrame(capture);
cvShowImage("Camera_Output", frame);
key = cvWaitKey(10);
if (key == 27){
break;
}
}
cvReleaseCapture(&capture);
cvDestroyWindow("Camera_Output");
return 0;
}
The output resolution is 320x240 and I want a 256x256 resolution. I think it's not possible because the camera manages its output video stream buffer and it has to keep the same ratio (width/height). What do you think about this idea ?
Is there a function which can force the resolution as a square resolution using OpenCV ?
Thanks a lot in advance for your help.
Seems like you video source does not handle 256x256 resolution. If you want to display it as such, you will have to crop the image yourself before displaying it.
Simple, you can do this by:
VideoCapture cap;
cap.open(0); // open your web-camera
cap.set(CV_CAP_PROP_FRAME_WIDTH, 256);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, 256);
If this doesn't work, you need to resize it manually by calling cv::resize().
Here is a link to the type of images my program produces: http://imgur.com/a/vibBx#0
I am trying out a simple capture test program that I have written. I am trying to capture images in a loop and save them onto the board properly numbered. The first capture sometimes is corrupted and the subsequent captures are a mix of two images. I have also observed that sometimes the upper half of the image is from the previous capture and the lower half is the capture from that cycle. I have given the details and the code below.
OpenCV 2.4.2 running on BeagleBone Black which has Ångström installed on it.
The camera which is plugged to the USB of BeagleBone Black is Logitech C920.
The camera is connected to BeagleBone Black before power up through the 5 V power supply and connecting BeagleBone Black to the laptop. Access is through PuTTY.
Code
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>
#include <string>
#include <unistd.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <cxcore.h>
#include "LaserWeed.h"
#include "SimpleGPIO.h"
using namespace cv;
int main(int argc, char* argv[])
{
int i=0, a;
string name;
int length;
char c, Filename[10000];
CvCapture* capture = NULL;
IplImage* img = NULL;
do
{
//I am not sure if this is necessary, but I tried anyway
//to see if it makes a difference since upper half of
//image was from previous cycle.
capture = NULL;
img = NULL;
//Converting Numbers to string to save with proper name
std::stringstream ss;
ss << i;
name = ss.str();
name = name + ".jpg";
length = name.size();
for(a=0; a<length; a++)
{
Filename[a] = name[a];
}
capture = cvCaptureFromCAM(-1);
if (!capture)
{
fprintf( stderr, "ERROR: capture is NULL \n" );
getchar();
return -1;
}
img = cvQueryFrame(capture);
if (!img)
{
fprintf(stderr, "ERROR: img is null...\n");
getchar();
return -1;
}
cvSaveImage(Filename,img);
cvReleaseCapture(&capture);
cvReleaseImage(&img);
i++;
c = getchar();
}
while (c!='e')
;
return 0;
}
Where might I be going wrong?
The Stack Overflow question BeagleBone, OpenCV and webcam issue somewhat has a similar problem. But reinstallation of the OS will be my last option.
This is weird, anyway try to take the capture out of the do-while loop, maybe opening and releasing the capture device each time won't give enough time for the camera to prepare it's image buffers.
I am trying to implement a grabcut algorithm in OpenCV using C++
I stumble upon this site and found a very simple way how to do it. Unfortunately, it seems like the code is not working for me
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main( )
{
// Open another image
Mat image;
image= cv::imread("images/mango11a.jpg");
// define bounding rectangle
cv::Rect rectangle(50,70,image.cols-150,image.rows-180);
cv::Mat result; // segmentation result (4 possible values)
cv::Mat bgModel,fgModel; // the models (internally used)
// GrabCut segmentation
cv::grabCut(image, // input image
result, // segmentation result
rectangle,// rectangle containing foreground
bgModel,fgModel, // models
1, // number of iterations
cv::GC_INIT_WITH_RECT); // use rectangle
cout << "oks pa dito" <<endl;
// Get the pixels marked as likely foreground
cv::compare(result,cv::GC_PR_FGD,result,cv::CMP_EQ);
// Generate output image
cv::Mat foreground(image.size(),CV_8UC3,cv::Scalar(255,255,255));
image.copyTo(foreground,result); // bg pixels not copied
// draw rectangle on original image
cv::rectangle(image, rectangle, cv::Scalar(255,255,255),1);
cv::namedWindow("Image");
cv::imshow("Image",image);
// display result
cv::namedWindow("Segmented Image");
cv::imshow("Segmented Image",foreground);
waitKey();
return 0;
}
Can anyone help me with this please? What is supposed to be the problem
PS: NO errors were printed while compiling.
check your settings again. I just executed the same tutorial and it worked fine for me.
I'm using tesseract 3.02 and opencv to let the tesseract recognize the text from my camera realtime.
But the effect is quite bad. Results are unreadable and can't show image fluently. I think it's the problem of my code.
Can some one give me advice about how to modify it?
Thanks a lot!
#include "stdafx.h"
#include <string>
#include <opencv2/opencv.hpp>
#include <time.h>
using namespace std;
using namespace cv;
int main() {
// [1]
tesseract::TessBaseAPI *myOCR =
new tesseract::TessBaseAPI();
// [2]
printf("Tesseract-ocr version: %s\n",
myOCR->Version());
printf("Leptonica version: %s\n",
getLeptonicaVersion());
// [3]
if (myOCR->Init(NULL, "eng")) {
fprintf(stderr, "Could not initialize tesseract.\n");
exit(1);
}
//声明IplImage指针
IplImage* pFrame = NULL;
//获取摄像头
CvCapture* pCapture = cvCreateCameraCapture(-1);
//创建窗口
cvNamedWindow("video", 1);
//显示视屏
time_t last_time = time(NULL);
while(1)
{
pFrame=cvQueryFrame( pCapture );
if(!pFrame) break;
cvShowImage("video",pFrame);
char c=cvWaitKey(33);
if(c==27)break;
time_t this_time = time(NULL);
if(this_time != last_time)
{
last_time = this_time;
myOCR->SetRectangle(0,0,pFrame->width,pFrame->height);
myOCR->SetImage((uchar*)pFrame->imageData,pFrame->width,pFrame- >height,pFrame->depth/8,pFrame->width*(pFrame->depth/8));
myOCR->Recognize(NULL);
const char* out = myOCR->GetUTF8Text();
printf("%s\n",out);
}
}
cvReleaseCapture(&pCapture);
cvDestroyWindow("video");
cv::waitKey(-1);
return 0;
}
Tesseract was designed to process scanned books. It operates on white pages where there is only black text, clearly seen with minimal distortions. Images are mostly Black & White. Your image is grey level so Tesseract will perform very very poor.
It is not a problem of your code but of Tesseract.
If you point your camera towards a book, you will be able to get the text (assuming image is focused) but if you want to read general text (like street signs, logo on someones T-shirt than there is no way to do it. Sorry to disappoint you.
However, if you want to recognize a specific text, like credit card numbers or street signs,
that you can do it.
Start by grabbing many imgages of your text.
Do a bit of
pre-processing on the image, convert it to BW,
train Tesseract on many examples.
And then it will be able to accomplish your task.
I am trying to read an AVI file using openCV. After getting the capture, the problem comes when I give a condition to the while loop which governs the extent to which queryFrame will be done.
There are total 1251 frames in the video.
When I use while (counter <= number_of_frames), the video runs fine and,
when I use while (cvQueryFrame(capture)), the video runs fine till 200-250th frame, then suddenly it starts running faster and finishes by 625th frame. I printed the FPS, it remains same all the time.
Why is this happening ??
Please help!
try the following...
C style reading..
#include <opencv2/video/video.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
int main()
{
CvCapture *video;
video = cvCreateFileCapture("ADDRESS TO THE FILE");
IplImage *frame;
while(true)
{
frame = cvQueryFrame(video);
if(frame->imageData==NULL)
{
std::cout<<"END OF VIDEO"<<std::endl;
break;
}
cvShowImage("VIDEO",frame);
cvWiatKey(25);//SINCE MOST OF THE VIDEOS RUN AT 25 FPS
}
return 0;
}
C++ STYLE....
int main()
{
VideoCapture video("ADDRESS OF VIDEO");
Mat frame;
while(true)
{
video >> frame;
if(frame.data==NULL)
{
std::cout<<"END OF VIDEO FILE"<<std::endl;
break;
}
imshow("VIDEO",frame);
waitKey(25);
}
return 0;
}
try this...and check if it gives an uniform rate of play...