I'm working on object detection using dlib 19.6 c++, till now i was using single classification like below
, these labels are generated using imglab from dlib.
For this I'm using fhog_object_detector_ex.cpp. It works well and able to detect object.
Now I have defined multi classifier like below.
1. clock
2. pot
so how can i use/modify fhog_object_detector_ex.cpp to train data. I have knowledge on how to test image,
std::vector<object_detector<image_scanner_type> > my_detectors;
my_detectors.push_back(detector1); // clock.svm
my_detectors.push_back(detector2); // pot.svm
my_detectors.push_back(detector3); // any other.svm
std::vector dets2 = evaluate_detectors(my_detectors, image);
but i'm not sure how can i train data. do i need to label 2 times separately for each image and run object trainer 2 times? or it is possible to train 2 classifiers same time?
Dlib HOG detector doesn't support multiclass classifier.SO you need to train two separate detectors for each label and then combine detectors to run on a single image based on weight index you get the label of the detector.
Related
I'm trying to to add noise to an Image & then denoised to see the difference in my object detection algorithm. So I developed OpenCV code in C++ for detection some objects in the image. I would like to test the robustness of the code, so tried to add some noises. In that way would like to check how the object detection rate changed when add noises to the image. So , first added some random Gaussian Noises like this
cv::Mat noise(src.size(),src.type());
float m = (10,12,34);
float sigma = (1,5,50);
cv::randn(noise, m, sigma); //mean and variance
src += noise;
I got this images:
The original:
The noisy one
So is there any better model for noises? Then how to Denoise it. Is there any DeNoising algorithms?
OpenCV comes with Photo package in which you can find an implementation of Non-local Means Denoising algorithm. The documentation can be found here:
http://docs.opencv.org/3.0-beta/modules/photo/doc/denoising.html
As far as I know it's the only suitable denoising algorithm both in OpenCV 2.4 and OpenCV 3.x
I'm not aware of any other noise models in OpenCV than randn. It shouldn't be a problem however to add a custom function that does that. There are some nice examples in python (you should have no problem rewriting it to C++ as the OpenCV API remains roughly identical) How to add noise (Gaussian/salt and pepper etc) to image in Python with OpenCV
There's also one thing I don't understand: If you can generate noise, why would you denoise the image using some algorithm if you already have the original image without noise?
Check this tutorial it might help you.
http://docs.opencv.org/trunk/d5/d69/tutorial_py_non_local_means.html
Specially this part:
OpenCV provides four variations of this technique.
cv2.fastNlMeansDenoising() - works with a single grayscale images
cv2.fastNlMeansDenoisingColored() - works with a color image.
cv2.fastNlMeansDenoisingMulti() - works with image sequence captured
in short period of time (grayscale images)
cv2.fastNlMeansDenoisingColoredMulti() - same as above, but for color
images.
Common arguments are:
h : parameter deciding filter strength. Higher h value removes noise
better, but removes details of image also. (10 is ok)
hForColorComponents : same as h, but for color images only. (normally
same as h)
templateWindowSize : should be odd. (recommended 7)
searchWindowSize : should be odd. (recommended 21)
And to add gaussian noise to image, maybe this thread will be helpful:
How to add Noise to Color Image - Opencv
I am sorry it seems a starting question but just wondering can i use rectangular dimensions for training opencv haar cascade. I tried with square samples and the resultant image was detected fine but when i tried with rectangular width and height as for license plate the aspect ratio is 2:1 between width and height so i am using the same aspect ratio while training but the resultant classifier is not detecting anything in the image.
nStages = 14
nPositive = 1780
minHitrate = 0.996
maxFalseAlarm = 0.2
nNegatives = 14000
width = 48
height = 24
Haar classifier type = BASIC
Boost type = gentle adaboost
The above are the parameters i have set for training of the classifier. Can anyone please confirm that can i use rectangular parameters for positive samples or not. Also please suggest some modifications to have the training done properly.
The size of negative images for training is around 240x161 annd 420x240
Thank you.
EDIT 1:
I am using the call as follows.
f_cascade.detectMultiScale( image, detected_objects, pyramidScale, 2, 0|CV_HAAR_SCALE_IMAGE);
The key parts of this are making sure your positive samples and training dimensions are the same. There is no reason why you won't be able to detect a rectangular object.
They key thing to remember is that traincascade is running whatever dimensions you specify over your images.
See here for some proof that rectangular objects should be detected just fine:
http://coding-robin.de/2013/07/22/train-your-own-opencv-haar-classifier.html
Also I wrote a tutorial about object detection if anyone gets stuck on this stuff:
http://johnallen.github.io/opencv-object-detection-tutorial/
I've been stuck on this for some time now. OpenCV's SVM implementation doesn't seem to work for a linear kernel. I'm fairly sure there's no bug in the code: when I change the kernel_type to RBF or POLY, keeping everything else as is, it works.
The reason I say it doesn't work is, I save the generated model and check it out. It shows support vector count as 1. Which is not the case in RBF or POLYnomial kernels.
There's nothing special about the code in itself, I've used OpenCV's SVM implementation before, but never a linear kernel. I tried setting the degree to 1 in a POLY kernel and it results in the same model. Which makes me believe something is buggy here.
The code structure, if required:
Mat trainingdata; //acquire from files. done and correct.
Mat testingdata; //acquire from files. done and correct again.
Mat labels; //corresponding labels. checked and correct.
SVM my_svm;
SVMParams my_params;
my_params.svm_type = SVM::C_SVC;
my_params.kernel_type = SVM::LINEAR; //or poly, with my_params.degree = 1.
my_param.C = 0.02; //doesn't matter if I set it to 20000, makes no difference.
my_svm.train( trainingdata, labels, Mat(), Mat(), my_params );
//train_auto(..) function with 10-fold cross-validation takes the same time as above (~2sec)!
Mat responses;
my_svm.predict( testingdata, responses );
//responses matrix is all wrong.
I have 500 samples from one class and 600 from the other class to test, and the correct classifications I get are: 1/500 and 597/600.
Craziest part:
I have done the same experiment with the same data on libSVM's MATLAB wrapper, and it works. Was just trying to do an OpenCV version of it.
It is not a bug that you always get only one support vector with linear CvSVM.
OpenCV optimizes a linear SVM down to one support vector.
The idea here is that the support vectors define the classification margin, and to do the actual classification only the separating hyperplane is needed and it can be defined by only one vector.
Parameter C doesn't matter if your training data is linearly separable. Maybe it is your case.
I've pasted all my code here in case you'd need that to understand my question: Plotting a graph on axes but getting no results while trying to classify image based on HoG features
My question is: given approximately 500 images (the Caltech "Cars 2001" dataset) with 48 HoG features each, what possible reasons can there be for the boosting to terminate early? What could cause a perfect fit, or a problem with the boosted sample weights, and how can such problems be solved? The specific algorithm I'm using is SAMME, a multiclass Adaboost classifier. I'm using Python 2.7 on Anaconda.
When I checked certain variables during the classification of my dataset, setting the n_estimators parameter to be 600, I found that:
discrete_test_errors: consisted of 1 item instead of being an array of 600 values
discrete_estimator_errors: was again one single value instead of of being an array of 600 values
real_test_errors is just one item again instead of 600
discrete_estimator_weights: array ([1.]) "
n_trees_discrete and n_trees_real: 1 instead of 600
Problem solved. My training array, labels, had no negatives, it consisted only of labels for one class. Of course the training would terminate immediately!
I have come across one problem when trying to train data with SVM.
I get some different regions (set of connected pixels) from face images, and regions from eyes are very similar, so I want to use Hu moments for shape description and SVM for training.
But SVM does not work properly, method svm.predict evaluates afterwards everything as non-eye, moreover the same regions which were labeled and used in traning phase as eye, are evaluated as non-eye.
Feature data consists only of 7 Hu moments. I will post here some samples of source code in a moment, thanks in advance :)
Additional info:
input image:
http://i.stack.imgur.com/GyLO0.png
Setting up basic svm for 1 image:
int image_regions = 10;
Mat training_mat(image_regions ,7,CV_32FC1); // 7 hu moments
Mat labels(image_regions ,1,CV_32FC1); // for labels 1 (eye) and -1 (non eye)
// computing hu moments
Moments moments2=moments(croppedImage,false);
double hu[7];
HuMoments(moments2,hu);
// putting them into svm traning mat
for (int k=0;k<huCounter;k++)
training_mat.at<float>(counter,k) = hu[k]; // counter is current number of region
if (isEye(...))
{
labels.at<float>(counter,0)=1.0;
}
else
{
labels.at<float>(counter,0)=-1.0;
}
//I use the following:
CvSVM svm;
CvSVMParams params;
params.svm_type = CvSVM::C_SVC;
params.kernel_type = CvSVM::LINEAR;
params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 1000, 1e-6);
// ... do the above mentioned phase, and then:
svm.train(training_mat, labels, Mat(), Mat(), params);
I hope the following suggestions can help you…..
The simplest task is to use a clustering algorithm and try to cluster the data into two classes. If an algorithm like ‘k-means’ can do the job why make things complex by using SVM and Neural Nets. I suggest you use this technique because your feature vector dimension is of a very small size (7 Hu Moments) as well as your number of samples.
Perform feature Normalization (specified in point 4) to make sure the values fall in a limited range.
Check out “is your data really separable?” As your data is small, take a few samples from positive images and a few samples from negative images and plot the feature vectors. If you can visually see the difference surely any learning algorithm can do the job for you. As I said earlier simple tricks can do better than complex math.
Only if you then decide to use SVM you should know the following:
• As I can see from your code you are using a Linear SVM, may be your data is non-separable by a linear kernel. Try using some polynomial kernel or other kernels. There is one option bool CvSVM::train_auto in openCV just have a look.
• Try to check whether the feature vector values you are getting are proper values or not (make sure that they are not some garbage values).
• Also you can perform feature normalization “ZERO MEAN and UNIT VARIENCE” before you use it for training.
• Most importantly increase the number of images for training, both positively and negatively labeled.
• Last but not least SVM is not magic, at the end of the day it is just drawing a line between two sets of points. So don’t expect it to classify anything you give it as input.
If nothing works “Just improve your feature extraction technique”