I have been trying to develop a program - written with C++ and using OpenCV -which counts the overall value of coins shown in some image.
I should note that I am new to the opencv platform.
In order to achieve this goal, as far as I understand - there has to be a use of the Hough transform to detect the ratio of the coins. I found this code example on the OpenCV site, but I can't put a value for the coins.
Here is what I have done so far.
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
using namespace std;
using namespace cv;
namespace
{
const std::string windowName = "Coins detection";
const std::string cannyThresholdTrackbarName = "Canny threshold";
const std::string accumulatorThresholdTrackbarName = "Accumulator Threshold";
const int cannyThresholdInitialValue = 41;
const int accumulatorThresholdInitialValue = 87;
const int maxAccumulatorThreshold = 200;
const int maxCannyThreshold = 255;
void HoughDetection(const Mat& src_gray, const Mat& src_display, int cannyThreshold, int accumulatorThreshold)
{
std::vector<Vec3f> circles;
HoughCircles( src_gray, circles, HOUGH_GRADIENT, 1, src_gray.rows/8, cannyThreshold, accumulatorThreshold, 0, 0 );
Mat display = src_display.clone();
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( display, center, 3, Scalar(0,255,0), -1, 8, 0 );
circle( display, center, radius, Scalar(0,0,255), 3, 8, 0 );
}
imshow( windowName, display);
}
}
int main(int argc, char** argv)
{
Mat src, src_gray;
String imageName("c:\\moedas.jpg");
if (argc > 1)
{
imageName = argv[1];
}
src = imread( imageName, IMREAD_COLOR );
if( src.empty() )
{
std::cerr<<"Invalid input image\n";
return -1;
}
cvtColor( src, src_gray, COLOR_BGR2GRAY );
GaussianBlur( src_gray, src_gray, Size(9, 9), 2, 2 );
int cannyThreshold = cannyThresholdInitialValue;
int accumulatorThreshold = accumulatorThresholdInitialValue;
namedWindow( windowName, WINDOW_AUTOSIZE );
createTrackbar(cannyThresholdTrackbarName, windowName, &cannyThreshold,maxCannyThreshold);
createTrackbar(accumulatorThresholdTrackbarName, windowName, &accumulatorThreshold, maxAccumulatorThreshold);
char key = 0;
while(key != 'q' && key != 'Q')
{
cannyThreshold = std::max(cannyThreshold, 1);
accumulatorThreshold = std::max(accumulatorThreshold, 1);
HoughDetection(src_gray, src, cannyThreshold, accumulatorThreshold);
key = (char)waitKey(10);
}
return 0;
}
The code you have so far only segments circle shapes in an input image. This is just the first step to count the coins. There are many ways to perform that task, ranging from simple contour counting techniques to complicated deep learning, and the explanation of such techniques is too broad and large in scope to put efficiently and concisely in an SO answer. However, here are some coin detectors/counter implementations/tutorials that you can check:
Implementation 1 in Python. This is the best of the list, although the code file is larger than yours, not too hard to port to C++. It has the best detection/counting performance but deals with Neural Networks, specifically, a Multilayer Perceptron.
Implementation 2 in Python. This is a very small code file, nearly as large as yours and has no idiomatic Python code, porting it to C++ is a no brainer, you should start here. This implementation uses mere contour counting with the aid of the Canny edge detector.
Tutorial 1 in C++. A simple tutorial in C++, but only serves introductory purposes, the implementations listed above are the real thing.
Related
I am very new to OpenCV and I am trying to detect just the penny image, but I am getting a bunch of smaller circles. Can someone tell me what Im doing wrong?
Code from here: https://github.com/opencv/opencv/blob/master/samples/cpp/houghcircles.cpp
Only things I changed were to make min circle radius 400, and max of circle 0. Because I know the image will be 600x480 so the penny circle must be at least 400.
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
static void help()
{
cout << "\nThis program demonstrates circle finding with the Hough transform.\n"
"Usage:\n"
"./houghcircles <image_name>, Default is ../data/board.jpg\n" << endl;
}
int main(int argc, char** argv)
{
cv::CommandLineParser parser(argc, argv,
"{help h ||}{#image|../data/board.jpg|}"
);
if (parser.has("help"))
{
help();
return 0;
}
//![load]
string filename = parser.get<string>("#image");
Mat img = imread(filename, IMREAD_COLOR);
if(img.empty())
{
help();
cout << "can not open " << filename << endl;
return -1;
}
//![load]
//![convert_to_gray]
Mat gray;
cvtColor(img, gray, COLOR_BGR2GRAY);
//![convert_to_gray]
//![reduce_noise]
medianBlur(gray, gray, 5);
//![reduce_noise]
//![houghcircles]
vector<Vec3f> circles;
HoughCircles(gray, circles, HOUGH_GRADIENT, 1,
gray.rows/16, // change this value to detect circles with different distances to each other
100, 30, 400,0 // change the last two parameters
// (min_radius & max_radius) to detect larger circles
);
//![houghcircles]
//![draw]
for( size_t i = 0; i < circles.size(); i++ )
{
Vec3i c = circles[i];
circle( img, Point(c[0], c[1]), c[2], Scalar(0,0,255), 3, LINE_AA);
circle( img, Point(c[0], c[1]), 2, Scalar(0,255,0), 3, LINE_AA);
}
//![draw]
//![display]
imshow("detected circles", img);
waitKey();
//![display]
return 0;
}
You've got radius and diameter mixed up. Your minimum radius cannot be 400 if your image is only 600x480. Set your min_radius to 200.
HoughCircles(gray, circles, HOUGH_GRADIENT, 1,
max(gray.cols,gray.rows), // to find only the biggest perfect circle
100, 100, 0,0 // leave other params as default
);
I'm trying to use Harris Corner detection algorithm of OpenCV to find corners in an image. I want to track it across consecutive frames using Lucas-Kanade Pyramidal Optical flow.
I have this C++ code, which doesn't seem to work for some reason:
#include <stdio.h>
#include "opencv2/core/core.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/opencv.hpp"
using namespace cv;
using namespace std;
void main()
{
Mat img1, img2;
Mat disp1, disp2;
int thresh = 200;
vector<Point2f> left_corners;
vector<Point2f> right_corners;
vector<unsigned char> status;
vector<float> error;
Size s;
s.height = 400;
s.width = 400;
img1 = imread("D:\\img_l.jpg",0);
img2 = imread("D:\\img_r.jpg",0);
resize(img2, img2, s, 0, 0, INTER_CUBIC);
resize(img1, img1, s, 0, 0, INTER_CUBIC);
disp1 = Mat::zeros( img1.size(), CV_32FC1 );
disp2 = Mat::zeros( img2.size(), CV_32FC1 );
int blockSize = 2;
int apertureSize = 3;
double k = 0.04;
cornerHarris( img1, disp1, blockSize, apertureSize, k, BORDER_DEFAULT );
normalize( disp1, disp1, 0, 255, NORM_MINMAX, CV_32FC1, Mat() );
for( int j = 0; j < disp1.size().height ; j++ )
{
for( int i = 0; i < disp1.size().width; i++ )
{
if( (int) disp1.at<float>(j,i) > thresh )
{
left_corners.push_back(Point2f( j, i ));
}
}
}
right_corners.resize(left_corners.size());
calcOpticalFlowPyrLK(img1,img2,left_corners,right_corners,status,error, Size(11,11),5);
printf("Vector size : %d",left_corners.size());
waitKey(0);
}
When I run it, I get the following error message:
Microsoft Visual Studio C Runtime Library has detected a fatal error in OpenCVTest.exe.
(OpenCVTest being the name of my project)
OpenCV Error: Assertion failed ((npoints = prevPtsMat.checkVector(2, CV_32F, true)) >= 0) in unknown function, file ..\..\OpenCV-2.3.0-win-src\OpenCV-2.3.0\modules\video\src\lkpyramid.cpp, line 71
I have been trying to debug this from yesterday, but in vain. Please help.
As we can see in the source code, this error is thrown if the previous points array is in someway faulty. Exactly what makes it bad is hard to say since the documentation for checkVector is a bit sketchy. You can still look at the code to find out.
But my guess is that your left_corners variable have either the wrong type (not CV_32F) or the wrong shape.
I am an IT engineer student.
My intention is to work on Landmark Guide System which is related to AR.
Part of that project is of course object recognition.
Currently my task is to recognize object from (webcam)
That's why I tried to use image histogram on openCV to select relative images to frame from dataset.So then i can perform SURF in a few images.
But the result is terrible. Almost all images gave the same result after comparing histograms.
I have
10200 ukbenchmark image datasets
from given frame i should recognize the object among 10200 images. But to perform SURF with that amount is impossible. I need to select somehow relative(potential for matching) images.
How to select images so i don't have to perform SURF with every single image?
Is there any way to exploit image histograms to solve this problem?
I would greatly appreciate your help guys!
Here is my dataset
Here is histogram comparision results
Here is my code based on opencv
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
int main( int argc, char** argv )
{
Mat src;
/// Establish the number of bins
int histSize = 256;
/// Set the ranges ( for B,G,R) )
float range[] = { 0, 256 } ;
const float* histRange = { range };
bool uniform = true; bool accumulate = false;
Mat gray_hist;
// Draw the histograms for B, G and R
int hist_w = 512; int hist_h = 400;
int bin_w = cvRound( (double) hist_w/histSize );
char * filename=new char[100];
//cycle starts here
int begin=getTickCount();
Mat inputImage=imread("frame3.jpg",1);//this is given input image
cvtColor(inputImage,inputImage,COLOR_RGB2GRAY);
Mat inputImageHist;
equalizeHist(inputImage,inputImage);
calcHist( &inputImage, 1, 0, Mat(), inputImageHist, 1, &histSize, &histRange, uniform, accumulate );
normalize( inputImageHist, inputImageHist, 0, 1, NORM_MINMAX, -1, Mat() );
for(int i=0;i<n;i++){
/// Load image
sprintf(filename,"D:\\labworks\\ukbenchmark\\full\\ukbench%05d.jpg",i);
src = imread( filename, 1 );
Mat srcGray;
cvtColor(src,srcGray,COLOR_RGB2GRAY);
//this commented lines are to show what i store in files
///// Apply Histogram Equalization
//equalizeHist( srcGray, srcGray);
//calcHist( &srcGray, 1, 0, Mat(), gray_hist, 1, &histSize, &histRange, uniform, accumulate );
//normalize( gray_hist, gray_hist, 0, 1, NORM_MINMAX, -1, Mat() );
/// Compute the histograms:
sprintf(filename,"histogramEqualized\\ukbench%05d.yml",i);
FileStorage fs(filename,FileStorage::READ);
fs["myHistogram"]>>gray_hist;
fs.release();
int histDif=compareHist(gray_hist,inputImageHist,1);
cout<<filename<<"\t:\t"<<histDif<<endl;
}
//cycle ends here
system("pause");
return 0;
}
I am doing face detection from video. So I wrote one small code to detect the face.
#include<opencv2/objdetect/objdetect.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <stdio.h>
#include<cv.h>
using namespace std;
using namespace cv;
CvCapture *capture=cvCaptureFromFile("foot.mp4");
double min_face_size=30;
double max_face_size=400;
Mat detectFace(Mat src);
int main( )
{
namedWindow( "window1", 1 );
while(1)
{
Mat frame,frame1;
frame1=cvQueryFrame(capture);;
frame=detectFace(frame1);
imshow( "window1", frame );
if(waitKey(1) == 'c') break;
}
waitKey(0);
return 0;
}
Mat detectFace(Mat image)
{
CascadeClassifier face_cascade( "haarcascade_frontalface_alt2.xml" );
CvPoint ul,lr;
std::vector<Rect> faces;
face_cascade.detectMultiScale( image, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(min_face_size, min_face_size),Size(max_face_size, max_face_size) );
for( int i = 0; i < faces.size(); i++ )
{
min_face_size = faces[i].width*0.8;
max_face_size = faces[i].width*1.2;
ul.x=faces[i].x;
ul.y=faces[i].y;
lr.x=faces[i].x + faces[i].width;
lr.y=faces[i].y + faces[i].height;
rectangle(image,ul,lr,CV_RGB(1,255,0),3,8,0);
}
return image;
}
I took one video for face detection which contains both small and large faces. My problem is using my code, it detects only small faces and also it shows some unwanted detection.
I need to detect both small and large faces in a video. How shall I do this?
Is there any problem with the scaling factor?
Please help me understand this problem.
Try to increase 'double max_face_size', which controls how large faces you want to detect.
You can also increase '2' in the parameters of 'detectMultiScale()', which controls the quality of the faces.
I am trying to use opencv to automatically find and locate all parking spots in an empty parking lot.
Currently, I have a code that thresholds the image, applies canny edge detection, and then uses probabilistic hough lines to find the lines that mark each parking spot.
The program then draws the lines and the points that make up the lines
Here is the code:
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int threshold_value = 150;
int threshold_type = 0;;
int const max_value = 255;
int const max_type = 4;
int const max_BINARY_value = 255;
int houghthresh = 50;
char* trackbar_value = "Value";
char* window_name = "Find Lines";
int main(int argc, char** argv)
{
const char* filename = argc >= 2 ? argv[1] : "pic1.jpg";
VideoCapture cap(0);
Mat src, dst, cdst, tdst, bgrdst;
namedWindow( window_name, CV_WINDOW_AUTOSIZE );
createTrackbar( trackbar_value,
window_name, &threshold_value,
max_value);
while(1)
{
cap >> src;
cvtColor(src, dst, CV_RGB2GRAY);
threshold( dst, tdst, threshold_value, max_BINARY_value,threshold_type );
Canny(tdst, cdst, 50, 200, 3);
cvtColor(tdst, bgrdst, CV_GRAY2BGR);
vector<Vec4i> lines;
HoughLinesP(cdst, lines, 1, CV_PI/180, houghthresh, 50, 10 );
for( size_t i = 0; i < lines.size(); i++ )
{
Vec4i l = lines[i];
line( bgrdst, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,255,0), 2, CV_AA);
circle( bgrdst,
Point(l[0], l[1]),
5,
Scalar( 0, 0, 255 ),
-1,
8 );
circle( bgrdst,
Point(l[2], l[3]),
5,
Scalar( 0, 0, 255 ),
-1,
8 );
}
imshow("source", src);
imshow(window_name, bgrdst);
waitKey(1);
}
return 0;
}
Currently, my main problem is figuring out how to extrapolate the line data to find the locations of each parking space. My goal is to have opencv find the parking spaces and draw out rectangles on each parking space with a number labeling the spots.
I think there are some major problems with the method I am currently using, because as shown in the output images, opencv is detecting multiple points on the line other than the 2 endpoints. That might make it very hard to use opencv to connect 2 adjacent endpoints.
I read something about using convex hull, but I am not exactly sure what it does and how it works.
Any help will be appreciated.
Here are the output images from my program:
http://imageshack.us/photo/my-images/22/test1hl.png/
http://imageshack.us/photo/my-images/822/test2lw.png/
Consider thinning your binary image, and then detect the end points and the branch points. Here is one such result based on the images provided; end points are in red and branch points are in blue.
Now you can find the locations of the parking spaces. A pair of blue dots is always connected by a single edge. Each blue dot is connected to either two or three red points. Then there are several ways to find the parking space formed by two blue dots and two red dots, the simplest is along the lines: find the closest pair of red dots where one dot is connected to a certain blue dot, and the other red point is connected to the other blue dot. This step can also be complemented by checking how close to parallel lines are the edges considered.