my project scope is currency note identification by comparing the sample images feature set.There, i have completed the feature extraction part of the sample images. Further i need to store the sample images features in the text file or XML file and the classification of them.
please help me to do the image classification part by using SVM classifier on the OpenCv
this is the feature extraction code that i have completed.
int main( intargc, char** argv )
{
/Loading the image as gray scale/
//declaring Mat object.This will holds an image(like iplimage in old opencv versions).
Mat gray_scale_img;
//imread is used to load an image. in here i have load the image as a grayscale image.
gray_scale_img=imread("100.jpg",CV_LOAD_IMAGE_GRAYSCALE);
/*surf detector settings*/
//setting the threshold value.high value will result low number of keypoints.
int hessian=100;
//initializing the surf keypoint detector
SurfFeatureDetectordetector(hessian);
/*detect surf key points*/
//creating vector to store detected keypoints
std::vector<KeyPoint>keypoints;
//detect keypoints
detector.detect(gray_scale_img,keypoints);
/*extract descriptor vectors/feature vectors from each and every keypoints */
SurfDescriptorExtractor extractor;
//this mat object will goinf to hold the extracted descriptors.
Mat descriptors;
//extracting descriptors/features
extractor.compute(gray_scale_img,keypoints,descriptors);
}
SVM in OpenCV is implemented in CvSVM class;
You need to have feature vector in form of a Matrix (row wise).
Assuming you are using height, width as your feature vector, your mat will be as follows (assuming you have 20 feature vectors):
Mat FV(20,2, CV_32F);
Mat flagmat(20,1,CV_8U);
/*
code to populate the matrix FV.
Fill the matrix with values so that it will look something as follows:
20 30
30 40
..
..
code to populate the matrix flagmat.
Fill the matrix with labels of each corresponding feature vector in matrix FV. It will look something as follows:
1
-1
1
1
-1
1
1
1
..
*/
CvSVM svm;
svm.train(datamat, flagmat,Mat(),Mat(),CvSVMParams());
Mat testFV(20,2,CV_32F);
Mat sample(1,2,CV_32F);
/* similarly as described above fill testFV matrix*/
float res;// to store result
for(int i =0;i<testFV.rows;i++)
{
sample.at<float>(0,0)=testFV.at<float>(i,0);
sample.at<float>(0,1)=testFV.at<float>(i,1);
float res = svm.predict(sample);
cout<<"predicted label: "<<res<<endl;
}
I'm assuming you can extract numerical values from the feature descriptors/vectors and put them in the sample matrix in above code. You can replace the feature vectors with any feature descriptor that you are using.
Related
With std::vector<cv::Mat> matList with several 2D Mat in that vector, one has to access the pixel values in the third dimension by using, e.g., matList.at(k).at<float>(i, j). Instead, i'd like to have a 3D mat, (mat3D) so that I would access that same pixel using mat3D.at<float>(i, j, k). k can be equal to up to several hundreds. The rows and columns are typically above 2000. What would be the most efficient way(s) to make this conversion, apart from assigning each pixel explicitly from the vector of 2D Mat objects to this 3D Mat object?
I've been following the Caffe MINST example and trying to deploy a test of the trained model with C++ where I use OpenCV to read in the images. In the example, they mention how for the training and test images they
scale the incoming pixels so that they are in the range [0,1). Why
0.00390625? It is 1 divided by 256.
I've heard how there's a DataTransformer class in Caffe you can use to scale your images, but if I multiplied each pixel in the OpenCV Mat object by 0.00390625 would this give the same result?
The idea is right. But remember to convert your OpenCV Mats to float or double type before scaling.
Something like:
cv::Mat mat; // assume this is one of your images (grayscale)
/* convert it to float */
mat.convertTo(mat, CV_32FC1); // use CV_32FC3 for color images
/* scaling here */
mat = mat * 0.00390625;
Update #1: Converting and scaling can also simply be done in one line, i.e.
cv::Mat mat; // assume this is one of your images (grayscale)
/* convert and scale here */
mat.convertTo(mat, CV_32FC1, 0.00390625);
I am doing a project of combining multiple images similar to HDR in iOS. I have managed to get 3 images of different exposures through the Camera and now I want to align them because during the capture, one's hand must have shaken and resulted in all 3 images having slightly different alignment.
I have imported OpenCV framework and I have been exploring functions in OpenCV to align/register images, but found nothing. Is there actually a function in OpenCV to achieve this? If not, is there any other alternatives?
Thanks!
In OpenCV 3.0 you can use findTransformECC. I have copied this ECC Image Alignment code from LearnOpenCV.com where a very similar problem is solved for aligning color channels. The post also contains code in Python. Hope this helps.
// Read the images to be aligned
Mat im1 = imread("images/image1.jpg");
Mat im2 = imread("images/image2.jpg");
// Convert images to gray scale;
Mat im1_gray, im2_gray;
cvtColor(im1, im1_gray, CV_BGR2GRAY);
cvtColor(im2, im2_gray, CV_BGR2GRAY);
// Define the motion model
const int warp_mode = MOTION_EUCLIDEAN;
// Set a 2x3 or 3x3 warp matrix depending on the motion model.
Mat warp_matrix;
// Initialize the matrix to identity
if ( warp_mode == MOTION_HOMOGRAPHY )
warp_matrix = Mat::eye(3, 3, CV_32F);
else
warp_matrix = Mat::eye(2, 3, CV_32F);
// Specify the number of iterations.
int number_of_iterations = 5000;
// Specify the threshold of the increment
// in the correlation coefficient between two iterations
double termination_eps = 1e-10;
// Define termination criteria
TermCriteria criteria (TermCriteria::COUNT+TermCriteria::EPS, number_of_iterations, termination_eps);
// Run the ECC algorithm. The results are stored in warp_matrix.
findTransformECC(
im1_gray,
im2_gray,
warp_matrix,
warp_mode,
criteria
);
// Storage for warped image.
Mat im2_aligned;
if (warp_mode != MOTION_HOMOGRAPHY)
// Use warpAffine for Translation, Euclidean and Affine
warpAffine(im2, im2_aligned, warp_matrix, im1.size(), INTER_LINEAR + WARP_INVERSE_MAP);
else
// Use warpPerspective for Homography
warpPerspective (im2, im2_aligned, warp_matrix, im1.size(),INTER_LINEAR + WARP_INVERSE_MAP);
// Show final result
imshow("Image 1", im1);
imshow("Image 2", im2);
imshow("Image 2 Aligned", im2_aligned);
waitKey(0);
There is no single function called something like align, you need to do/implement it yourself, or find an already implemented one.
Here is a one solution.
You need to extract keypoints from all 3 images and try to match them. Be sure that your keypoint extraction technique is invariant to illumination changes since all have different intensity values because of different exposures. You need to match your keypoints and find some disparity. Then you can use disparity to align your images.
Remember this answer is so superficial, for details first you need to do some research about keypoint/descriptor extraction, and keypoint/descriptor matching.
Good luck!
//make every image as a row vector
Mat data = formatImagesForPca(v);
//apply PCA
PCA pca(data, cv::Mat(), CV_PCA_DATA_AS_ROW, k);
//project in some kxk dimension
Mat p = pca.project(data);
//calculate eigenvalues
Mat eigenval = pca.eigenvectors.clone();
i have applied pca but
i am facing problem in extracting the eigenvalues after applying pca.
i want to extract features using pca. but how can i reduce dimension and extract features and what is wrong with this code ?
https://github.com/Itseez/opencv/blob/master/samples/cpp/pca.cpp
http://www.bytefish.de/blog/pca_in_opencv/
I hope these code can help you.
I am having some problem with Mat in OpenCV. I was using SIFT for image classification with SVM. Now I realized that the true-positive rate was low, so I decided to add ORB feature detectors on top of SIFT. My problem is that, for example for one image:
SIFT descriptors: Mat size [128 x 250]
ORB descriptors: Mat size [32 x 400]
Now as for training matrix all the features have to be in the training matrix and than trained. Now, as you see that the 2 matrix of SIFT and ORB are of different size. How can I combine them into one matrix?.
Do I have to append (add) the second matrix to the end of the first one because currently I am assigning it to separate columns.
Please give me some hints on this please.
There are two parts to extracting features based on your solution. The first part is to detect keypoints, and the second part is to describe them. At the moment, you are doing both stages with both SIFT and ORB, and coming up with matrices of different sizes. Instead, use the following framework:
// Construct detectors
cv::FeatureDetector siftDetector, orbDetector;
siftDetector.create("SIFT");
orbDetector.create("ORB");
// Detect keypoints
std::vector<cv::Keypoint> siftPoints, orbPoints;
siftDetector.detect(img, siftPoints);
orbDetector.detect(img, orbPoints);
// Concantenate the vectors
siftPoints.insert(siftPoints.end(), orbPoints.begin(), orbPoints.end());
// Construct descriptor (SIFT used as example)
cv::FeatureDescriptor siftDescriptor;
siftDescriptor.create("SIFT");
// Compute descriptors
cv::Mat descriptors;
siftDescriptor.compute(img, siftPoints, descriptors);
You now have SIFT descriptions for all detected keypoints.
PS: I haven't compiled this code, so double check for typos and syntax.