I am trying to overlay an image over the video capture of my program with OpenCV but I am having trouble getting it to work. I set the a region of interest in the original frame taken from the webcam in the form of a rectangle. Then i copy it to the original frame. However it never shows up on the new frame captured by the webcam. I tested it and the image is loading correctly but it is not being copied to the new frame for some reason.
Code Below in C++:
#include<opencv2/core/core.hpp>
#include<opencv2/contrib/contrib.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<iostream>
#include<vector>
using namespace std;
using namespace cv;
int main(){
VideoCapture cap;
cap.open(0);
if(!cap.isOpened()){
cerr << "Error opening the webcam!" << endl;
return -1;
}
for(;;){
Mat frame;
cap>>frame;
Mat newFrame;
frame.copyTo(newFrame);
Mat image = imread("C:\\User\\Desktop\\images\\image.png");
int cx = (newFrame.cols - 70) / 2;
if (image.data) {
// Get a BGR version of the face, since the output is BGR color
Mat srcBGR = Mat(face.size(), CV_8UC3);
cvtColor(image, srcBGR, CV_GRAY2BGR);
// Get the destination ROI (and make sure it is within the image)
Rect dstRC = Rect(cx, newFrame.rows/2, 70, 70);
Mat dstROI = newFrame(dstRC);
// Copy the pixels from src to dst.
srcBGR.copyTo(dstROI);
}
imshow("frame", newFrame);
char key = (char) waitKey(30);
// Exit this loop on escape:
if(key == 27)
break;
}
return 0;
}
Any suggestions or help would be appreciated. Thanks.
You converted image to BGR by using not converted one:
change this: image.copyTo(dstROI); to this srcBGR.copyTo(dstROI);
#include<opencv2/core/core.hpp>
#include<opencv2/contrib/contrib.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<iostream>
#include<vector>
using namespace std;
using namespace cv;
int main(){
VideoCapture cap;
cap.open(0);
if(!cap.isOpened()){
cerr << "Error opening the webcam!" << endl;
return -1;
}
Mat image = imread("D:\\ImagesForTest\\Lena.jpg",0);
cv::resize(image,image,Size(70,70));
Mat frame;
for(;;){
cap>>frame;
Mat newFrame=frame.clone();
int cx = (newFrame.cols - 70) / 2;
if (!image.empty()) {
// Get a BGR version of the face, since the output is BGR color
Mat srcBGR = Mat(image.size(), CV_8UC3);
cvtColor(image, srcBGR, CV_GRAY2BGR);
// Get the destination ROI (and make sure it is within the image)
Rect dstRC = Rect(cx, newFrame.rows/2, 70, 70);
Mat dstROI = newFrame(dstRC);
// Copy the pixels from src to dst.
srcBGR.copyTo(dstROI);
}
imshow("frame", newFrame);
char key = (char) waitKey(30);
// Exit this loop on escape:
if(key == 27)
break;
}
return 0;
}
Related
The below code captures the given video and outputs the frames using imshow() function only when the statement calling the function detectMultiScale() is commented. Is it only to me? If no, then why so?
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main() {
VideoCapture cap("test.mp4");
cap.set(CV_CAP_PROP_FRAME_WIDTH, 640);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
if (!cap.isOpened()) {
cout << "\nCould not open video file\n";
return -1;
}
Mat img;
HOGDescriptor hog;
hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());
namedWindow("video capture", CV_WINDOW_AUTOSIZE);
while (true) {
cap >> img;
if (!img.data)
continue;
vector<Rect> found, found_filtered;
// hog.detectMultiScale(img, found, 0, Size(4, 4), Size(8, 8), 1.05, 2);
imshow("video capture", img);
waitKey(30);
}
return 0;
}
I am working on visual studio 2010 C++ and Opencv 2.3.1. Using HP laptop windows 7 32 bit. I really have tried many times to solve this problem but it still happening. My built-in webcam with some codes (some times works and some times not ) and with some other codes it always displays a gray window instead of camera feed?
could anyone help?
Thanks in advance.
For Example The first code sometimes display cam feed and the second one always display gray window
#include "opencv2/opencv.hpp"
using namespace cv;
using namespace std;
int main(int, char**)
{
VideoCapture cap(0); // open the default camera
if (!cap.isOpened()) // check if we succeeded
return -1;
Ptr<BackgroundSubtractor> pMOG = new BackgroundSubtractorMOG2();
Mat fg_mask;
Mat frame;
int count = -1;
for (;;)
{
// Get frame
cap >> frame; // get a new frame from camera
// Update counter
++count;
// Background subtraction
pMOG->operator()(frame, fg_mask);
imshow("frame", frame);
imshow("fg_mask", fg_mask);
// Save foreground mask
string name = "mask_" + std::to_string(static_cast<long long>(count)) + ".png";
imwrite("D:\\SO\\temp\\" + name, fg_mask);
if (waitKey(1) >= 0) break;
}
// the camera will be deinitialized automatically in VideoCapture destructor
return 0;
}
////////////////////////
second code:
// WriteVideo.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char* argv[])
{
VideoCapture cap(0); // open the video camera no. 0
if (!cap.isOpened()) // if not success, exit program
{
cout << "ERROR: Cannot open the video file" << endl;
return -1;
}
namedWindow("MyVideo",CV_WINDOW_AUTOSIZE); //create a window called "MyVideo"
double dWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH); //get the width of frames of the video
double dHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT); //get the height of frames of the video
cout << "Frame Size = " << dWidth << "x" << dHeight << endl;
Size frameSize(static_cast<int>(dWidth), static_cast<int>(dHeight));
VideoWriter oVideoWriter ("D:/visual outs/mix/WriteVideo.avi", CV_FOURCC('P','I','M','1'), 20, frameSize, true); //initialize the VideoWriter object
if ( !oVideoWriter.isOpened() ) //if not initialize the VideoWriter successfully, exit the program
{
cout << "ERROR: Failed to write the video" << endl;
return -1;
}
while (1)
{
Mat frame;
bool bSuccess = cap.read(frame); // read a new frame from video
if (!bSuccess) //if not success, break loop
{
cout << "ERROR: Cannot read a frame from video file" << endl;
break;
}
oVideoWriter.write(frame); //writer the frame into the file
imshow("MyVideo", frame); //show the frame in "MyVideo" window
if (waitKey(10) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
{
cout << "esc key is pressed by user" << endl;
break;
}
}
return 0;
}
Without the actual code, there's nothing we can really do in order to pinpoint the issue. Could you reformulate your question please? Anyway, in order to instantiate a VideoCapture object in OpenCV, the C++ code would be pretty much something like this
#include "opencv2/opencv.hpp"
using namespace cv;
int main(int, char**)
{
VideoCapture cap(0); // open the default camera
if(!cap.isOpened()) // check if we succeeded
return -1;
Mat edges;
namedWindow("edges",1);
for(;;)
{
Mat frame;
cap >> frame; // get a new frame from camera
cvtColor(frame, edges, CV_BGR2GRAY);
GaussianBlur(edges, edges, Size(7,7), 1.5, 1.5);
Canny(edges, edges, 0, 30, 3);
imshow("edges", edges);
if(waitKey(30) >= 0) break; // Wait 30 ms for a key feed, then break out of the code if a keypress is found in the message queue
}
// the camera will be deinitialized automatically in VideoCapture destructor
return 0;
}
As for the standard C version, you'd have to leverage the old yet still reliable CvCapture struct which is contained in the old OpenCV API. In this case, you'd act upon the cvCreateCameraCapture(0) which simply returns a pointer to the newly created camera instance (CvCapture). In the latter case, the code would evaluate to the snipper hereunder.
# include "highgui.h"
# include "cv.h"
int main( int argc, char** argv )
{
CvCapture* capture;
capture = cvCreateCameraCapture(0);
if (!capture)
return -1;
IplImage* bgr_frame = cvQueryFrame(capture); // Query the next frame
CvSize size = cvSize(
(int)cvGetCaptureProperty(capture,
CV_CAP_PROP_FRAME_WIDTH),
(int)cvGetCaptureProperty(capture,
CV_CAP_PROP_FRAME_HEIGHT)
);
cvNamedWindow("OpenCV via CvCapture", CV_WINDOW_AUTOSIZE); // Create a window and assign it a title
/* Open a CvVideoWriter to save the video to a file. Think of it as a stream */
CvVideoWriter *writer = cvCreateVideoWriter(argv[1],
CV_FOURCC('D','I','V','X'),
30,
size
);
while((bgr_frame = cvQueryFrame(capture)) != NULL)
{
cvWriteFrame(writer, bgr_frame);
cvShowImage("OpenCV via CvCapture", bgr_frame);
char c = cvWaitKey(30); // Same as the snippet above. Wait for 30 ms
if(c == 27) break; // If the key code is 0x27 (ESC), break
}
cvReleaseVideoWriter(&writer); // Dispose the CvVideoWriter instance
cvReleaseCapture(&capture); // Dispose the CvCapture instance
cvDestroyWindow("OpenCV via CvCapture"); // Destroy the window
return 0;
}
I have written a program in opencv(c++) to manipulate camera property. I am trying to blur my camera display using "track bar". The code is working but in certain condition. It works, when i change the position of "track bar" using mouse click. But if i tried to slide the track bar it gives me an error as mention below.
Here is my code
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
Mat image, image_blurred;
int slider=5;
float sigma=0.3 *((slider - 1)*0.5 - 1) +0.8;
void on_Trackbar(int,void *)
{
int k_size = max(1,slider);
//k_size = k_size%2 == 0 ? k_size+1 : k_size;
setTrackbarPos("kernel","Blur window",3);
sigma=0.3 *((slider - 1)*0.5 - 1) +0.8;
GaussianBlur(image,image_blurred,Size(3,3),sigma);
}
int main()
{
Mat img;
VideoCapture cap(0);
if(!cap.isOpened())
{
cout<<"Camera is not successfully opened"<<endl;
return -1;
}
namedWindow("original image",CV_WINDOW_AUTOSIZE);
namedWindow("Blur Image",CV_WINDOW_AUTOSIZE);
while(!char(waitKey(30)=='q') && cap.isOpened())
{
cap>>img;
GaussianBlur(img,image_blurred,Size(slider,slider),sigma);
createTrackbar("kernel","Blur Image",&slider,21,on_Trackbar);
imshow("Blur Image",image_blurred);
imshow("original image",img);
}
destroyAllWindows();
return 0;
}
Please give your valuable views. Thanks in advance!!.
In the while loop, you're passing an invalid value to GaussianBlur, since slider can also be an even number.
You can correct this introducing a new variable int kernel_size = 2*slider+1. slider now is the radius of the kernel, and kernel_size is guaranteed to be odd.
Also you don't need to call GaussianBlur in the callback function, since it's already called in the main loop. The only goal of the callback is to update the values of kernel_size and sigma.
This code will work as expected:
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
Mat image, image_blurred;
int slider = 0;
int kernel_size = 3;
float sigma = 0.3 *((kernel_size - 1)*0.5 - 1) + 0.8;
void on_Trackbar(int, void *)
{
kernel_size = 2 * slider + 1;
sigma = 0.3 *((kernel_size - 1)*0.5 - 1) + 0.8;
}
int main()
{
Mat img;
VideoCapture cap(0);
if (!cap.isOpened())
{
cout << "Camera is not successfully opened" << endl;
return -1;
}
namedWindow("original image", CV_WINDOW_AUTOSIZE);
namedWindow("Blur Image", CV_WINDOW_AUTOSIZE);
createTrackbar("kernel", "Blur Image", &slider, 21, on_Trackbar);
while (!char(waitKey(30) == 'q') && cap.isOpened())
{
cap >> img;
GaussianBlur(img, image_blurred, Size(kernel_size, kernel_size), sigma);
imshow("Blur Image", image_blurred);
imshow("original image", img);
}
destroyAllWindows();
return 0;
}
I'm trying to figure out how motion detection work in opencv.
I can see there the video analysis reference but I don't find enough information about how this is used.
I've also seen some people using absdiff I tried it like this, but It gives me an exception at memore errors
OpenCV Error: Sizes of input arguments do not match (The operation is neither 'a
rray op array' (where arrays have the same size and the same number of channels)
, nor 'array op scalar', nor 'scalar op array') in cv::arithm_op, file C:\builds
\2_4_PackSlave-win32-vc12-shared\opencv\modules\core\src\arithm.cpp, line 1287
the code is
#include <iostream>
#include <sstream>
#include <string>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
int main()
{
//create matrix for storage
Mat image;
Mat image2;
Mat image3;
Mat image4;
//initialize capture
VideoCapture cap;
cap.open(0);
//create window to show image
namedWindow("window", 1);
while (1){
//copy webcam stream to image
cap >> image;
cap >> image2;
absdiff(image, image2, image3);
threshold(image3, image4, 128, 255, THRESH_BINARY);
//print image to screen
if (!image.empty()) {
imshow("window", image3);
}
//delay33ms
waitKey(10);
//
}
}
im obviously not using it right
You need to confirm the VideoCapture was successful before using the images. Also, you want to test if the image was captured successfully before using it. Try this:
VideoCapture cap(0);
if(!cap.isOpened()) {
std::cerr << "Failed to open video capture" << std::endl;
return -1;
}
namedWindow("window");
while(true) {
cap >> image;
cap >> image2;
if(image.empty() || image2.empty()) {
std::cerr << "failed to capture images\n";
return -1;
}
absdiff(image, image2, image3);
threshold(image3, image4, 128, 255, THRESH_BINARY);
imshow("window", image);
int k = waitKey(30) & 0xff;
if('q' == k || 27 == k)
break;
}
I wrote a short routine in openCV and C++ to track objects with a webcam. The webcam formulation was speedy with no lag, but before leaving work for the weekend, I recorded a typical sequence to use as a test template while I work until Monday. This and the corresponding change in code somehow make the video play back in really slow motion. Here is the code, opening "Test.avi", ~20 seconds long instead of running a constant stream off of the webcam:
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <vector>
using namespace cv;
using namespace std;
Mat drawBoundingBoxes (Mat canvasImage, vector<vector<Point>> contours);
int main(int argc, char** argv[])
{
Mat frame;
Mat back;
Mat fGround;
BackgroundSubtractorMOG2 bGround;
bGround.nmixtures = 3;
//bGround.nShadowDetection = 0;
bGround.fTau = .5;
VideoCapture cap;
cap.open("Test.avi");
if (!cap.isOpened())
{
cout << "Can't open video" << endl;
return -1;
}
vector<vector<Point>> contours;
namedWindow("video", CV_WINDOW_AUTOSIZE);
while (true)
{
static int count = 1;
cap >> frame;
if (frame.empty())
break;
bGround.operator()(frame, fGround);
bGround.getBackgroundImage(back);
erode(fGround, fGround, Mat(), Point(-1,-1), 2, BORDER_DEFAULT);
dilate(fGround, fGround, Mat(), Point(-1,-1), 10, BORDER_DEFAULT);
if (count > 50)
{
findContours(fGround, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
drawContours(frame, contours, -1, Scalar(239,255,0), 2);
drawBoundingBoxes(frame, contours);
}
imshow("video", frame);
if(waitKey(30) >= 0)
break;
count++;
}
return 0;
}
Mat drawBoundingBoxes (Mat canvasImage, vector<vector<Point>> contours)
{
vector<Rect> boundRect(contours.size());
for (int i=0; i<contours.size(); i++)
{
boundRect[i] = boundingRect(contours[i]);
rectangle(canvasImage, boundRect[i], Scalar(153,0,76), 2, 8, 0);
}
return canvasImage;
}
Any ideas? Memory Leak somewhere? Thanks,
-Tony
I believe your recorded video has a higher framerate than that your PC can process real time. It's not a problem with a webcam as it just drops the frames. You could try to decrease the delay in the waitKey() procedure and see if that helps.