How to detect shift in static camera? - opencv

I'm looking for help in solving my problem. I have a static camera, which is focus on one place. I download current view at every 1 second.
I would like to write a program which detects when someone moves the camera in a different direction. After that I would like to generate image with the shift. I am currently come up with this solution:
Create a base frame, to which I compare all future frames.
Generate edge with Canny Edge algorithm.
Then I generate the corner points with Harris algorithm.
Then I want to compare the current frame with a base frame (picture, where are just corner points on black background) with calcOpticalFlowPyrLK (Lucas-Kanade method).
Unfortunately I have problems, because depending on the lighting, the number of people, etc., the edges and corners are change. Because of this I don't know if there was a shift or not.
Can somebody give me some advices any solution how to detect shift?
Thanks for your help :)

See the opencv's standard example:
opencv/samples/cpp/phase_corr.cpp
I think it is that you are looking for.

Related

OpenCV - align stack of images - different cameras

We have this camera array arranged in an arc around a person (red dot). Think The Matrix - each camera fires at the same time and then we create an animated gif from the output. The problem is that it is near impossible to align the cameras exactly and so I am looking for a way in OpenCV to align the images better and make it smoother.
Looking for general steps. I'm unsure of the order I would do it. If I start with image 1 and match 2 to it, then 2 is further from three than it was at the start. And so matching 3 to 2 would be more change... and the error would propagate. I have seen similar alignments done though. Any help much appreciated.
Here's a thought. How about performing a quick and very simple "calibration" of the imaging system by using a single reference point?
The best thing about this is you can try it out pretty quickly and even if results are too bad for you, they can give you some more insight into the problem. But the bad thing is it may just not be good enough because it's hard to think of anything "less advanced" than this. Here's the description:
Remove the object from the scene
Place a small object (let's call it a "dot") to position that rougly corresponds to center of mass of object you are about to record (the center of area denoted by red circle).
Record a single image with each camera
Use some simple algorithm to find the position of the dot on every image
Compute distances from dot positions to image centers on every image
Shift images by (-x, -y), where (x, y) is the above mentioned distance; after that, the dot should be located in the center of every image.
When recording an actual object, use these precomputed distances to shift all images. After you translate the images, they will be roughly aligned. But since you are shooting an object that is three-dimensional and has considerable size, I am not sure whether the alignment will be very convincing ... I wonder what results you'd get, actually.
If I understand the application correctly, you should be able to obtain the relative pose of each camera in your array using homographies:
https://docs.opencv.org/3.4.0/d9/dab/tutorial_homography.html
From here, the next step would be to correct for alignment issues by estimating the transform between each camera's actual position and their 'ideal' position in the array. These ideal positions could be computed relative to a single camera, or relative to the focus point of the array (which may help simplify calculation). For each image, applying this corrective transform will result in an image that 'looks like' it was taken from the 'ideal' position.
Note that you may need to estimate relative camera pose in 3-4 array 'sections', as it looks like you have a full 180deg array (e.g. estimate homographies for 4-5 cameras at a time). As long as you have some overlap between sections it should work out.
Most of my experience with this sort of thing comes from using MATLAB's stereo camera calibrator app and related functions. Their help page gives a good overview of how to get started estimating camera pose. OpenCV has similar functionality.
https://www.mathworks.com/help/vision/ug/stereo-camera-calibrator-app.html
The cited paper by Zhang gives a great description of the mathematics of pose estimation from correspondence, if you're interested.

Find corner coordinates in image using openCV

I'm new to image processing and hope someone can help/guide me in the right direction.
So I have a picture in black/white and I want to find the corner coordinates of the inner black part of the preprocessed picture. My question is what kind of method/s will yield the most accurate result?
I want something like this (red dots shows the inner corners)
go with cv::goodFeaturesToTrack() and play with params until you get your result.
you can refer to this on why choose this and not cornerHarris: goodFeaturesToTrack vs cornerHarris
and also to this SO answer for an example: opencv-using-cvgoodfeaturestotrack-with-c-mat-variable
of course I assume you are using C++, if you are using python it won't change much...
have luck and try to do a search before asking next time
I don't know what language you're using which makes it harder to answer this question but the way I did it my last time was by applying openCV's canny edge detection algorithm. This allows you to see the edges on the image. Next find the contours. With those two functions and a little help from your friend Google, you will be able to figure this out. Good luck!
One of the aproaches would be to use just sobel independently in X and Y (in original image). Since you have binary already just find inner edge, which will be easy.
Those edges can be then sampled - take a few points of the edge. And with the help of OpenCV library function cv::fitLine find the line of the edge. Do the same with all the inner edges and compute the intersections. This approach should be fairly accurate since from the fitLine function on you basically compute the corners in sub-pixel accuracy.

Determine movement/motion (in pixels) between two frames

First of all I'm a total newbie in image processing, so please don't be too harsh on me.
That being said, I'm developing an application to analyse changes in blood flow in extremities using thermal images obtained by a camera. The user is able to define a region of interest by placing a shape (circle,rectangle,etc.) on the current image. The user should then be able to see how the average temperature changes from frame to frame inside the specified ROI.
The problem is that some of the images are not steady, due to (small) movement by the test subject. My question is how can I determine the movement between the frames, so that I can relocate the ROI accordingly?
I'm using the Emgu OpenCV .Net wrapper for image processing.
What I've tried so far is calculating the center of gravity using GetMoments() on the biggest contour found and calculating the direction vector between this and the previous center of gravity. The ROI is then translated using this vector but the results are not that promising yet.
Is this the right way to do it or am I totally barking up the wrong tree?
------Edit------
Here are two sample images showing slight movement downwards to the right:
http://postimg.org/image/wznf2r27n/
Comparison between the contours:
http://postimg.org/image/4ldez2di1/
As you can see the shape of the contour is pretty much the same, although there are some small differences near the toes.
Seems like I was finally able to find a solution for my problem using optical flow based on the Lukas-Kanade method.
Just in case anyone else is wondering how to implement it in Emgu/C#, here's the link to a Emgu examples project, where they use Lukas-Kanade and Farneback's algorithms:
http://sourceforge.net/projects/emguexample/files/Image/BuildBackgroundImage.zip/download
You may need to adapt a few things, e.g. the parameters for the corner detection (the frame.GoodFeaturesToTrack(..) method) , but it's definetly something to start with.
Thanks for all the ideas!

Arrow recognition in video

I would like to create a program that can identify arrows in a video feed and determine the direction they are pointing at (left or right). My aim is to use this program with an arduino robot in order to determine the direction in which the bot should move.
my problem is which method to use. I ve narrowed my options down to template matching or SURF. template matching is good because it is rotation independent, therefore it can determine between left and right arrows. However since the bot will be moving, the size of the template arrow might not be equal to that of the video feed, resulting in no matches.
SURF solves this problem however it is rotation invariant. This means that Left arrows and right arrows will be considered as the same thing.
Can anyone please suggest an approach I can use for this program.
Thanks in advance for any help
P.S I will be using OpenCV for implementation.
I managed to solve the problem by using canny edge detection and HoughLinesP. The system works pretty well but has a limited rotation range at which it will detect the direction correctly (approx 15 degrees).
basically I first performed colour detection to detect the arrow, then used houghlinesp to find its outline. Out of these lines, I eliminated all those which are horizontal or vertical, leaving just the ones at the tip as shown in red. I then used the end points of each line to determine the direction.

How to detect PizzaMarker

did somebody tried to find a pizzamarker like this one with "only" OpenCV so far?
I was trying to detect this one but couldn't get good results so far. I do not know where this marker is in picture (no ROI is possible), the marker will be somewhere in the room (different ligthning effects) and not faceing orthoonal towards us. What I want - the corners and later the orientation of this marker extracted with the corners but first of all only the 5Corners. (up, down, left, right, center)
I was trying so far: threshold, noiseclearing, find contours but nothing realy helped for a good result. Chessboards or square markers are normaly found because of their (parallel) lines- i guess this can't help me here...
What is an easy way to find those markers?
How would you start?
Use other colorformat like HSV?
A step-by-step idea or tutorial would be realy helpfull. Cause i couldn't find tuts at the net. Maybe this marker isn't called pizzamarker -> does somebody knows the real name?
thx for help
First - thank you for all of your help.
It seems that several methods are usefull. Some more or less time expansive.
For me it was the easiest with a template matching but not with the same marker.
I used only a small part of it...
this can be found 5 times(4 times negative and one positive) in this new marker:
now I use only the 4 most negatives Points and the most positive and got my 5 points that I finaly wanted. To make this more sure, I check if they are close to each other and will do a cornerSubPix().
If you need something which can operate in real-time I'd go down the edge detection route and look for intersecting lines like these guys did. Seems fast and robust to lighting changes.
Read up on the Hough Line Transform in openCV to get started.
Addendum:
Black to White is the strongest edge you can have. If you create a gradient image and use the strongest edges found in the scene (via histogram or other) you will be able to limit the detection to only the black/white edges. Look for intersections. This should give you a small number of center points to apply Hough ellipse detection (or alternate) to. You could rotate in a template as a further check if you wish.
BTW.. OpenCV has Edge Detection, Hough transform and FitEllipse if you do go down this route.
actually this 'pizza' pattern is one of the building blocks of the haar featured used in the
Viola–Jones object detection framework.
So what I would do is compute the summed area table, or integral image using cv::integral(img) and then run exhaustive search for this pattern, on various scales (size dependant).
In each window you are using only 9 points (top-left, top-center, ..., bottom left).
You can train and use cvHaarDetectObjects to detect the marker using VJ.
Probably not the fastest method but it should work.
You can find more info on object detection methods using OpenCV here: http://opencv.willowgarage.com/documentation/object_detection.html

Resources