I am new in image processing and c++ programming. this is what i have done until now to be able to keep the coordinate of some certain points in a sequence of frame:
I could find the center of a circle in the frame1.
cv::HoughCircles( tmp2, circles, CV_HOUGH_GRADIENT, 1, 300, 300, 100);
for( size_t i = 0; i < circles.size(); i++ ){
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
cout << "center" << center.x << ", " << center.y << endl;
Vector.push_back(std::make_pair(center.x,center.y)); //coordinates of center points
int radius = cvRound(circles[i][2]);
// circle center
circle( tmp2, center, 3, 1 , -1, 8, 0 );
// circle outline
circle( tmp2, center, radius, 1 , 3, 8, 0 );
}
}
what is this center point contains? does it contain pixel value in
that point?
if I have for example, 3 circle in frame1...is that a good way to copy(make_pair) them in a vector?
how to track these center points in the frame2 to find their new coordinates?
thanks in advance..
Yes, center contains coordinates, it is structure with fields x and y.
It depends on what do you need after this. How do you want to process them further?
Multiple object tracking depends on which kind of images do you have. You cannot "track" just centers of the circles without any prior information. Is it synthetic circles, or just some real objects or something else? Check the first answer here, it is relevant.
Related
I am trying to detect the circle inside traffic light, and I am able to detect only 1 out of the 2 circle, and the size of the circle which i am getting seems to be too big
Input Image: https://i.imgur.com/VkNDt2B.png
Output image: https://i.imgur.com/BBq5tE0.png
int main()
{
Mat src, gray;
src = imread("C:\/test_image2.png", 1);
resize(src, src, Size(640, 480));
cvtColor(src, gray, CV_BGR2GRAY);
// Reduce the noise so we avoid false circle detection
GaussianBlur(gray, gray, Size(9, 9), 2, 2);
vector<Vec3f> circles;
// Apply the Hough Transform to find the circles
HoughCircles(gray, circles, CV_HOUGH_GRADIENT, 1, 60, 200, 20, 0, 35);
// Draw the circles detected
for (size_t i = 0; i < circles.size(); i++)
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
circle(src, center, 3, Scalar(0, 255, 0), -1, 8, 0);// circle center
circle(src, center, radius, Scalar(0, 0, 255), 3, 8, 0);// circle outline
cout << "center : " << center << "\nradius : " << radius << endl;
}
// Show your results
namedWindow("Hough Circle Transform Demo", CV_WINDOW_AUTOSIZE);
imshow("Hough Circle Transform Demo", src);
waitKey(0);
return 0;
}
HoughCircles works best if you know in advance the approx size of the circles you're looking for. I suggest you give a better value for min_radius and max_radius parameters.
In any case, you need to play with param1 and param2 parameters. If circles are not perfect circles you can try to lower the image resolution using the dp parameter (f.ex. with dp = 2 the image is downscaled to half its resolution).
Basically: play with param1 and param2 until your circles are detected, no matter if other circles are detected. Use this result to find out what radius your circles are, then fix the min and max radius to remove most circles you don't want and finally play again with param1 and param2 until only your circles are left.
this is a pretty huge image
try cropping to the traffic light part first ( to get something to begin with ) and then by trying different combinations of min_distance and param_1,param_2 parameter try getting most circles ( even the wrong ones ) detected. find out what values get the most circles and what combination gets least ( or no ) circles and then fine tune the parameters to get lesser circles detected and finally find the perfect combination
1.Some Information: I would like to develop a kind of circle recognition with the help of openCV. I successfully set up a connection between Swift, objc-c++, but strangely I have some problems with the circle recognition algorithm: Not all of the circles in my image gets detected!
2.Have a look at my code:
+(UIImage *)ConvertImage:(UIImage *)image {
cv::Mat matImage;
UIImageToMat(image, matImage);
cv::Mat modImage;
cv::medianBlur(matImage, matImage, 5);
cv::cvtColor(matImage, modImage, CV_RGB2GRAY);
cv::GaussianBlur(modImage, modImage, cv::Size(9, 9), 2, 2);
vector<Vec3f> circles;
cv::HoughCircles(modImage, circles, CV_HOUGH_GRADIENT, 1, 1, 100, 50, 0, 0);
for (auto i = circles.begin(); i != circles.end(); ++i)
std::cout << *i << ' ';
for( size_t i = 0; i < circles.size(); i++ )
{
cv::Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
circle( matImage, center, 3, Scalar(0,255,0), -1, 8, 0 );
circle( matImage, center, radius, Scalar(0,0,255), 3, 8, 0 );
}
UIImage *binImg = MatToUIImage(matImage);
return binImg;
}
As you can see in the image [click] there appears this issue :
Only 3 of 7 circles gets detected!
So in the docs I found the parameters explanation for this line:
cv::HoughCircles(modImage, circles, CV_HOUGH_GRADIENT, 1, 1, 100, 50, 0, 0);
dp = 1: The inverse ratio of resolution.
min_dist = modImage.rows/8: Minimum distance between detected centers.
param_1 = 200: Upper threshold for the internal Canny edge detector.
param_2 = 100*: Threshold for center detection.
min_radius = 0: Minimum radio to be detected. If unknown, put zero as default.
max_radius = 0: Maximum radius to be detected. If unknown, put zero as default.
3.My question
How to get rid of the issue mentioned above?
Any help would be very appreciated :)
For issue number 2 : The outline should be colored, not white!
What color should it be? At any rate you draw that circle in your code with this line.
circle( matImage, center, radius, Scalar(0,0,255), 3, 8, 0 );
If you want to change the color you can change the values you have declared in Scalar(0,0,255).
If you dont want the circle there at all you can remove that line of code.
Your images seems to be noise free. If the image is to contain circle always, You can extract the contours and fit circles using Least Squares
You can get the circle fit equations here. It is a straightforward implementation. Create a structure for the circle parameters (center and radius), fit circle and store the parameters in the structure and use it to draw circle using OpenCV.
You can also generate points on the circle using "ellipse2poly" function.
I am using c++ with OpenCV 3.0 to create a basic form of SimulCam.
I am currently stuck on finding a way to check when the object ball has crossed/intersected with a line that I have drawn on the output window.
The ball is being tracked using contours, and ultimately I would like to work out the exact frame number this intersect happens at.
But first, I would like to understand how to perform the check to see when the Object ball has crossed/intersected with the drawn line.
Scene with ball moving towards line
I have the contours for the object, I would like to understand how to perform the check of an intersection.
Code for finding contours and Object Tracking:
findContours(resizedThresh, contourVector, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));
contourVector.resize(contourVector.size());
line(resizedF_Fast, Point(300, 0), Point(300, 360), Scalar(255), 2, 8);
for (size_t i = 0; i < contourVector.size(); i++) {
approxPolyDP(Mat(contourVector[i]), contourVector[i], 0.01*arcLength(contourVector[i], true), true);
double area = contourArea(contourVector[i]);
if (contourVector[i].size() > 5 && (area > 200)) {
++circlesC;
drawContours(resizedF_Fast, contourVector, i, Scalar(255, 255, 255), 2, CV_AA, hierarchy, abs(1));
searchForMovement(resizedThresh, resizedF_Fast);
}
}
I have done some other research, and I have been looking into using lineIterator, but i'm not entirely sure..
Apologies for the potential crude code, novice here. Any help would be greatly appreciated.
My first approach would be to fit a circle into your contour points and then compute the distance between the line and your circle center with the dot product. Maybe like this (didnt tried it out):
Point Pc; // circle center
Point L0(300,0);
Point L1(300,360);
double v[] = {L1.x-L0.x,L1.y-L0.y};
double w[] = {Pc.x-L0.x,Pc.y-L0.y};
Mat v(1,2,CV_32F,v);
Mat w(1,2,CV_32F,w);
double c1 = w.dot(v);
double c2 = v.dot(v);
double b = c1 / c2;
Mat Pb = L0 + b * v;
double distance = norm(Pc,Pb);
Then you check if your distance minus your circle radius is less equal zero.
But due to perspective transformation of your camera the ball becomes an ellipse and my assumption becomes less accurate.
If you need a more accurate solution you need to check every contour point and take the minimum distance.
This link shows some code and further explanations.
I finally worked through this, i'll post the general idea here.
For each frame, calculate the object contours.
each contour will have an x and y coordinate stored
Used LineIterator (e.g. lineIt) to cycle through all values of a line.
if (xpos_contour < lineIt.pos().x) {
// Object is on the left of the line
}
else if (xpos_contour > lineIt.pos().x) {
// Object is to the right of the line
}
Bear in mind the input video im using filmed top down, so only the x coordinate mattered.
I am doing a project in OpenCV on estimating the speed of moving vehicle using the video captured. Here the camera is stationary. I have estimated the speed of single object using centroid and Euclidean distance. Now the problem is, I am not getting how to do the same for multiple objects.
Here, I need to calculate the Euclidean distance of objects between 2 subsequent frames.
I am grateful if anyone would help.
I have created the class-
class centroids
{
public:
vector<Point2f> ce;
vector<float> area;
};
centroids c[100];
And this is the code I've written. I would be grateful if anyone helped me with the code:
findContours( fgMaskMOG2,
contours,
hierarchy,
CV_RETR_CCOMP,
CV_CHAIN_APPROX_SIMPLE );
int morph_size = 6;
Mat element = getStructuringElement( MORPH_RECT,
Size( 2*morph_size+1, 2*morph_size+1 ),
Point( morph_size, morph_size ) );
Scalar color( 255, 255, 255 ); // color of the contour in the
//Draw the contour and rectangle
for( int i = 0; i < contours.size(); i++ )
{
drawContours( fgMaskMOG2,
contours,
i,
color,
CV_FILLED,
8,
hierarchy );
}
//imshow("morpho window",dst);
vector<Moments> mu( contours.size() );
vector<Point2f> mc( contours.size() );
vector<Point2f> m ;
vector<double> time;
vector<Point2f> centroid( mc.size() );
//vector< vector<Point> >::iterator itc = contours.begin();
// iterate through each contour.
double time1[1000];
for( int i = 0; i < contours.size(); i++ )
{
// Find the area of contour
double a = contourArea( contours[i], false );
if( a > 500 )
{
mu[i] = moments( contours[i], false );
mc[i] = Point2f( (mu[i].m10 / mu[i].m00), (mu[i].m01 / mu[i].m00) );
m.push_back( mc[i] );
Point2f diff;
double euclidian = 0;
for( int f = 0; f < m.size(); f++ )
{
if( k == 1 )
{
c[f].ce.push_back( m[f] );
cout << "cen" << c[f].ce << endl;
euclidian = 0;
}
else
{
c[f+1].ce.push_back( m[f] );
cout << "cent" << c[f+1].ce << endl;
diff = c[f].ce[f] - c[f-1].ce[f-1];
euclidian = abs( sqrt( (diff.x*diff.x) + (diff.y*diff.y) ) );
cout << "euclidian" << euclidian << endl;
}
}
cout << "\n centroid" << m << endl;
circle( fgMaskMOG2,
mc[i],
5,
Scalar( 0, 0, 255 ),
1,
8,
0 );
}
}
Thanks in advance :)
You can estimate speed of a moving vehicle based on the video frames only if approximate distance between vehicle and camera is constant throughout the calculation i.e. vehicle is moving in a straight line perpendicular to the camera's vision. So, if camera is looking from side, all the vehicles will be at different distance and calculation will become highly inaccurate for multiple vehicles. Even the vehicles will overlap and their segmentation will be difficult.
There are two scenarios in which your calculation may work -
First, when the camera is capturing from top looking vertically down on vehicles. In this case, there will be a stark difference between the vehicle color and road color. You can use several ways to segment out those individual vehicles, tag them based on their features and identify those vehicles in next frame using the features. This way you'll get position of individual vehicles and then you can predict the speed based on your algorithm. These are following links which will be helpful for segmenting the vechicles -
How to define the markers for Watershed in OpenCV?
http://www.codeproject.com/Articles/751744/Image-Segmentation-using-Unsupervised-Watershed-Al
http://www.bogotobogo.com/python/OpenCV_Python/python_opencv3_Image_Watershed_Algorithm_Marker_Based_Segmentation.php
Second, when vehicles are moving in a single line behind one another. In this case, you can use a combination of color and contour based segmentation depending on the background of your vehicles. After segmentation you can again use object features to identify the position of objects in the next frame. Then run your algorithm for both cases.
If you have complete video sequence of the vehicles, you can segment out different vehicles in the first frame automatically or identify them manually, and then apply motion tracking on those identified objects. You can use Opencv's motion analysis functions and object tracking functions to do so. Thus you'll get position of all tracked vehicles in each frame. So you can easily run and test your speed calculating algorithms.
I am using this code to get the coordinate of the center of detected circles in the image.
vector<Vec3f> circles;
cv::HoughCircles( t, circles, CV_HOUGH_GRADIENT, 1, t.rows/8, 200, 100, 0, 0 );
for( size_t i = 0; i < circles.size(); i++ ){
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
cout << "center" << center << endl;
int radius = cvRound(circles[i][2]);
// circle center
circle( t2, center, 3, 1 , -1, 8, 0 );
// circle outline
circle( t2, center, radius, 1 , 3, 8, 0 );
}
imshow( "circles", t2 );
I can detect the circles but did no get any result for cooardinate of the center points :(
thanks in advance.
after edition:
I added this line but the answer was zero.
cout << "number of circles found: " << circles.size() << endl;
images:
the first one is the main circle and the second one is after applying gaussian filter and HoughCircles function:
If I understand you correctly your code Draws the circles but the
cout << "center" << center << endl;
line does not give the correct output.
This is because cv::Point does not support direct output via <<.
Try to use:
cout << "center" << center.x << ", " << center.y << endl;
If the Problem is that you canĀ“t find any circles make sure that the min_radius and max_radius are choosen correctly. Try starting with a wide range of allowed radii and then try to choose a smaller Range until you get only the circles you want.
This Values can make a huge difference in the detection Ratio.