few days I'm fighting with camera calibration with chessboard example. Everything is going fine (corners are found and displayed, then feed to arrays) till I call final function calibrateCamera. Than I get assertation error:
OpenCV Error: Assertion failed (nimages > 0) in calibrateCamera, file /home/ig/Downloads/opencv-2.4.8/modules/calib3d/src/calibration.cpp, line 3415
here is classic code:
#include <iostream>
#include <fstream>
#include <vector>
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;
int main(int argc, char* argv[])
{
VideoCapture captR(0); // open the video camera no. 0 (RIGHT)
if (!captR.isOpened()) // if not success, exit program
{
cout << "Cannot open the video cam 0" << endl;
return -1;
}
namedWindow("MyVideo (RIGHT)",CV_WINDOW_AUTOSIZE); //create a window called "MyVideo"
namedWindow("Grayscale",CV_WINDOW_AUTOSIZE); //create a window called "Grayscale"
int a = 0; // Frame counter
int numCornersHor = 7; // Chessboard dimensions
int numCornersVer = 5;
int numSquares = numCornersHor * numCornersVer;
Size boardSize = Size(numCornersHor, numCornersVer);
Mat frameR;
// Mat frameL;
Mat gray_frame;
vector<Point3f> obj;
vector<Point2f> corners; // output vectors of image points
for (int i=0; i<boardSize.height; i++) {
for (int j=0; j<boardSize.width; j++) {
obj.push_back(Point3f(i, j, 0.0f));
}
}
while (1){
int key = waitKey(30);
bool bCaptSuccessR = captR.read(frameR); // read a new frame from video
if (!bCaptSuccessR) //if capture not succeded, break loop
{
cout << "Cannot read a frame from video stream" << endl;
break;
}
vector<vector<Point3f> > object_points;
vector<vector<Point2f> > image_points;
// make grayscale frame version for conerSubPix
cvtColor(frameR, gray_frame, CV_BGR2GRAY);
// Get the chessboard corners
bool found = findChessboardCorners(frameR, boardSize, corners);
if (found) {
// Increase accuracy by subpixels
cornerSubPix(gray_frame, corners, Size(11, 11), Size(-1, -1), TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 30, 0.1));
drawChessboardCorners(gray_frame, boardSize, corners, found);
imshow("Grayscale", gray_frame);
////////////////////////////////////////////
if(key==32){ // Save good found by pressing [space]
image_points.push_back(corners);
object_points.push_back(obj);
cout << "Captured good calibration image, No " << a << endl;
cout << "corners: " << corners << endl;
//cout << "obj: " << obj << endl;
a++;
}
}
imshow("MyVideo (RIGHT)", frameR); //show right webcam frame in "MyVideo" window
if (key == 27) { //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
cout << "esc key is pressed by user" << endl;
break;
}
if (key == 115){ // If 'S' key pressed begin calibration
//////////// BEGIN CALIBRATION ////////////////////////
cout << "Callibration started..." << endl;
Mat cameraMatrix = Mat(3, 3, CV_64F);
cameraMatrix.at<double>(0,0) = 1.0;
Mat distCoeffs;
distCoeffs = Mat::zeros(8, 1, CV_64F);
vector<Mat> rvecs;
vector<Mat> tvecs;
Size imageSize = frameR.size();
calibrateCamera(object_points, image_points, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs);
cout << "Callibration ended." << endl;
}//callibration
}
captR.release();
return 0;
}
And here is OpenCV file excerpt with line numbers:
3400 double cv::calibrateCamera( InputArrayOfArrays _objectPoints,
3401 InputArrayOfArrays _imagePoints,
3402 Size imageSize, InputOutputArray _cameraMatrix, InputOutputArray _distCoeffs,
3403 OutputArrayOfArrays _rvecs, OutputArrayOfArrays _tvecs, int flags, TermCriteria criteria )
3404 {
3405 int rtype = CV_64F;
3406 Mat cameraMatrix = _cameraMatrix.getMat();
3407 cameraMatrix = prepareCameraMatrix(cameraMatrix, rtype);
3408 Mat distCoeffs = _distCoeffs.getMat();
3409 distCoeffs = prepareDistCoeffs(distCoeffs, rtype);
3410 if( !(flags & CALIB_RATIONAL_MODEL) )
3411 distCoeffs = distCoeffs.rows == 1 ? distCoeffs.colRange(0, 5) : distCoeffs.rowRange(0, 5);
3412
3413 int i;
3414 size_t nimages = _objectPoints.total();
3415 CV_Assert( nimages > 0 );
3416 Mat objPt, imgPt, npoints, rvecM((int)nimages, 3, CV_64FC1), tvecM((int)nimages, 3, CV_64FC1);
3417 collectCalibrationData( _objectPoints, _imagePoints, noArray(),
3418 objPt, imgPt, 0, npoints );
3419 CvMat c_objPt = objPt, c_imgPt = imgPt, c_npoints = npoints;
3420 CvMat c_cameraMatrix = cameraMatrix, c_distCoeffs = distCoeffs;
3421 CvMat c_rvecM = rvecM, c_tvecM = tvecM;
3422
3423 double reprojErr = cvCalibrateCamera2(&c_objPt, &c_imgPt, &c_npoints, imageSize,
3424 &c_cameraMatrix, &c_distCoeffs, &c_rvecM,
3425 &c_tvecM, flags, criteria );
3426
3427 bool rvecs_needed = _rvecs.needed(), tvecs_needed = _tvecs.needed();
3428
3429 if( rvecs_needed )
3430 _rvecs.create((int)nimages, 1, CV_64FC3);
3431 if( tvecs_needed )
3432 _tvecs.create((int)nimages, 1, CV_64FC3);
3433
Using Linux Ubuntu 12.04, OpenCV 2.4.8, gcc 4.6.3, Eclipse, ...
You are declaring object_points and image_points within the while loop, but probably want to put declarations outside of the loop. Otherwise, the lists will (effectively) be cleared after each iteration.
The user presses the first key, to detect the checkerboards. Boards are written to object_points and image_points. Then the user presses the key to calibrate the camera. Processing of the first key ends, object_points and image_points loose scope (and are cleared), processing of the second key starts, calibrateCamera is called with an empty object_points array and fails.
You should also check whether object_points is not empty before calling calibrateCamera.
You may also find the source code in the samples/cpp/tutorial_code/calib3d/camera_calibration/ folder of the OpenCV source library
Related
This question already has answers here:
imread returns None, violating assertion !_src.empty() in function 'cvtColor' error
(22 answers)
Closed 8 months ago.
I am trying to convert frames from a video to Tensors as the video is playing. This is my code:
#include <iostream>
#include "src/VideoProcessing.h"
#include <opencv2/opencv.hpp>
#include <opencv2/videoio.hpp>
typedef cv::Point3_<float> Pixel;
const uint WIDTH = 224;
const uint HEIGHT = 224;
const uint CHANNEL = 3;
const uint OUTDIM = 128;
void normalize(Pixel &pixel){
pixel.x = (pixel.x / 255.0 - 0.5) * 2.0;
pixel.y = (pixel.y / 255.0 - 0.5) * 2.0;
pixel.z = (pixel.z / 255.0 - 0.5) * 2.0;
}
int main() {
int fps = VideoProcessing::getFPS("trainer.mp4");
unsigned long size = VideoProcessing::getSize("trainer.mp4");
cv::VideoCapture cap("trainer.mp4");
//Check if input video exists
if(!cap.isOpened()){
std::cout<<"Error opening video stream or file"<<std::endl;
return -1;
}
//Create a window to show input video
cv::namedWindow("input video", cv::WINDOW_NORMAL);
//Keep playing video until video is completed
while(true){
cv::Mat frame;
frame.convertTo(frame, CV_32FC3);
cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB); // convert to float; BGR -> RGB
// normalize to -1 & 1
auto* pixel = frame.ptr<Pixel>(0,0);
const Pixel* endPixel = pixel + frame.cols * frame.rows;
for (; pixel != endPixel; pixel++){normalize(*pixel);}
// resize image as model input
cv::resize(frame, frame, cv::Size(WIDTH, HEIGHT));
//Capture frame by frame
bool success = cap.read(frame);
//If frame is empty then break the loop
if (!success){
std::cout << "Found the end of the video" << std::endl;
break;
}
//Show the current frame
cv::imshow("input video", frame);
if (cv::waitKey(10) == 27){
std::cout << "Esc key is pressed by user. Stopping the video" << std::endl;
break;
}
}
//Close window after input video is completed
cap.release();
//Destroy all the opened windows
cv::destroyAllWindows();
std::cout << "Video file FPS: " << fps << std::endl;
std::cout << "Video file size: " << size << std::endl;
return 0;
}
My goal (down the road) is to run inference on each frame to get landmarks. However, at this stage, I see this error:
terminate called after throwing an instance of 'cv::Exception'
what(): OpenCV(4.1.0) /home/onur/opencv/modules/imgproc/src/color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function 'cvtColor'
Aborted (core dumped)
Where am I going wrong?
You will have to read the frame before performing any conversion.
Move the part
//Capture frame by frame
bool success = cap.read(frame);
//If frame is empty then break the loop
if (!success){
std::cout << "Found the end of the video" << std::endl;
break;
}
Just after
cv::Mat frame;
I've trained a BOW codebook (vocabulary) using a A-KAZE feature descriptors and am trying to use a BFMatcher with knnMatch to compare newly extracted features to the codebook.
Instead, I get the following error,
OpenCV Error: Assertion failed (_queryDescriptors.type() == trainDescType) in knnMatchImpl, file /home/cecilia/opencv-3.0.0/modules/features2d/src/matchers.cpp, line 722 terminate called after throwing an instance of 'cv::Exception' what(): /home/cecilia/opencv-3.0.0/modules/features2d/src/matchers.cpp:722: error: (-215) _queryDescriptors.type() == trainDescType in function knnMatchImpl
I've using the following examples
BoW in OpenCV using precomputed features
How to train and predict using bag of words?
My intuition is that I am adding the codebook to the matcher incorrectly, but I can't find any documentation or examples that support another method. How can I use my codebook with new examples.
MCVE
/* BOWTest.cpp*/
#include <opencv2/imgcodecs.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/features2d.hpp>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <string>
#include <stdio.h>
#include <dirent.h>
using namespace cv;
using namespace std;
std::string outputFile = "test_codebook.png";
std::string trainingDir = "dataset/";
std::string outputPrefix = "output/res_custom_";
void train(Mat codebook, int codebook_n, Ptr<Feature2D> akaze);
void test(Mat codebook, Ptr<Feature2D> akaze);
int main(int ac, char** av) {
Ptr<Feature2D> feature = AKAZE::create();
Mat codebook;
int codebook_n = 100;
//train(codebook, codebook_n, feature);
test(codebook, feature);
}
//I included the train method to show how the codebook is trained, but it is not actually called in this example
void train(Mat codebook, int codebook_n, Ptr<Feature2D> akaze){
//defining terms for bowkmeans trainer
TermCriteria tc(TermCriteria::MAX_ITER + TermCriteria::EPS, 10, 0.001);
int retries = 1;
int flags = KMEANS_PP_CENTERS;
BOWKMeansTrainer bowTrainer(codebook_n, tc, retries, flags);
int i = 0;
unsigned long numPoints = 0;
DIR *d;
struct dirent *dir;
d = opendir(trainingDir.c_str());
if (d) {
while ((dir = readdir(d)) != NULL){
try {
Mat img;
std::string imgName = trainingDir + dir->d_name;
i = i + 1;
printf("%d, %lu: %s ...", i,numPoints, imgName.c_str());
img = imread(imgName, CV_LOAD_IMAGE_COLOR);
if(img.empty()){ //not image
printf("bad.\n");
continue;
}
printf("loaded.\n");
resize(img, img, Size(200, 200));
Mat features;
vector<KeyPoint> keypoints;
akaze->detectAndCompute(img, Mat(), keypoints, features);
features.convertTo(features, CV_32F);
bowTrainer.add(features);
Mat res;
drawKeypoints(img, keypoints, res);
std::string output_img = outputPrefix + dir->d_name;
imwrite(output_img, res);
numPoints += features.rows;
}catch(int e){
cout << "An exception occurred. Nr. " << e << '\n';
}
}
printf("Read images!");
closedir(d);
codebook = bowTrainer.cluster();
imwrite(outputFile, codebook);
}
}
void test(Mat codebook, Ptr<Feature2D> akaze){
codebook = imread(outputFile);
int codebook_n = codebook.rows;
BFMatcher matcher(NORM_L2);
matcher.add(std::vector<cv::Mat>(1, codebook));
Mat res(Size(codebook_n * 10, 3*10), CV_8UC3, Scalar(0));
vector<int> res_idx(codebook_n, 0);
try {
Mat img;
String imgName = trainingDir + "dog1.jpeg";
img = imread(imgName, CV_LOAD_IMAGE_COLOR);
if(img.empty()){ //not image
printf("bad.\n");
}else{
printf("loaded.\n");
resize(img, img, Size(200, 200));
Mat features;
vector<KeyPoint> keypoints;
akaze->detectAndCompute(img, noArray(), keypoints, features);
features.convertTo(features, CV_32F);
vector< vector< DMatch > > nn_matches;
matcher.knnMatch(features, nn_matches, 1);
printf("%d matched keypoints", nn_matches.size());
}
}catch(int e){
cout << "An exception occurred. Nr. " << e << '\n';
}
}
test_codebook.png
dog1.jpeg
Output
loaded.
OpenCV Error: Assertion failed (_queryDescriptors.type() == trainDescType) in knnMatchImpl, file /home/cecilia/opencv-3.0.0/modules/features2d/src/matchers.cpp, line 722
terminate called after throwing an instance of 'cv::Exception'
what(): /home/cecilia/opencv-3.0.0/modules/features2d/src/matchers.cpp:722: error: (-215) _queryDescriptors.type() == trainDescType in function knnMatchImpl
You shouldn't save the codebook as an image. imwrite will eventually scale and convert the values of the codebook. And imread with default parameters will load it as a 3 channel image CV_8UC3. To store matrices that are not strictly images, you should use FileStorage.
Save:
FileStorage fs(outputFile, FileStorage::WRITE);
// Store codebook
fs << "codebook" << codebook;
Load:
FileStorage fs(outputFile, FileStorage::READ);
fs["codebook"] >> codebook;
You should use BOWImgDescriptorExtractor to compute the BoW image descriptor starting from your features, AKAZE in this case:
Ptr<DescriptorMatcher> matcher = BFMatcher::create("BruteForce");
BOWImgDescriptorExtractor bow(akaze, matcher);
bow.setVocabulary(codebook);
// Mat img = ...
// AKAZE features
Mat features;
vector<KeyPoint> keypoints;
akaze->detectAndCompute(img, noArray(), keypoints, features);
features.convertTo(features, CV_32F);
// BoW descriptor
Mat bowFeatures;
vector<vector<int>> pointsIdxsOfCluster;
bow.compute(features, bowFeatures, &pointsIdxsOfCluster);
You can use builtin glob to read images from a folder, avoiding dirent.
vector<String> fileNames;
glob(trainingDir, fileNames);
for (int i=0; i<fileNames.size(); ++i)
{
Mat img = imread(fileNames[i]);
...
You can use iostream with cout, instead of printf.
This is how the code looks like:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
std::string outputFile = "test_codebook.yml";
std::string trainingDir = "path_to_train_folder/";
std::string outputPrefix = "path_to_output_folder/";
void train(Mat codebook, int codebook_n, Ptr<Feature2D> akaze);
void test(Mat codebook, Ptr<Feature2D> akaze);
int main(int ac, char** av) {
Ptr<Feature2D> feature = AKAZE::create();
Mat codebook;
int codebook_n = 100;
train(codebook, codebook_n, feature);
test(codebook, feature);
}
//I included the train method to show how the codebook is trained, but it is not actually called in this example
void train(Mat codebook, int codebook_n, Ptr<Feature2D> akaze){
//defining terms for bowkmeans trainer
TermCriteria tc(TermCriteria::MAX_ITER + TermCriteria::EPS, 10, 0.001);
int retries = 1;
int flags = KMEANS_PP_CENTERS;
BOWKMeansTrainer bowTrainer(codebook_n, tc, retries, flags);
int i = 0;
unsigned long numPoints = 0;
vector<String> fileNames;
glob(trainingDir, fileNames);
for (int i=0; i<fileNames.size(); ++i)
{
try {
Mat img;
std::string imgName = fileNames[i];
std::string filename = imgName.substr(trainingDir.length());
cout << i << ", " << numPoints << " : " << imgName;
img = imread(imgName, CV_LOAD_IMAGE_COLOR);
if (img.empty()){ //not image
cout << " bad" << endl;
continue;
}
cout << " loaded" << endl;
resize(img, img, Size(200, 200));
Mat features;
vector<KeyPoint> keypoints;
akaze->detectAndCompute(img, Mat(), keypoints, features);
features.convertTo(features, CV_32F);
bowTrainer.add(features);
Mat res;
drawKeypoints(img, keypoints, res);
std::string output_img = outputPrefix + filename;
imwrite(output_img, res);
numPoints += features.rows;
}
catch (int e){
cout << "An exception occurred. Nr. " << e << '\n';
}
}
cout << "Read images!" << endl;
codebook = bowTrainer.cluster();
{
FileStorage fs(outputFile, FileStorage::WRITE);
// Store codebook
fs << "codebook" << codebook;
// You can also store additional info, like the list of images
//// Store train images filenames
//fs << "train" << "[";
//for (int i = 0; i < fileNames.size(); ++i)
//{
// fs << fileNames[i];
//}
//fs << "]";
}
}
void test(Mat codebook, Ptr<Feature2D> akaze)
{
vector<String> trainFileNames;
{
FileStorage fs(outputFile, FileStorage::READ);
fs["codebook"] >> codebook;
/*FileNode trainingImages = fs["train"];
FileNodeIterator it = trainingImages.begin(), it_end = trainingImages.end();
int idx = 0;
for (; it != it_end; ++it, idx++)
{
trainFileNames.push_back(*it);
}*/
}
int codebook_n = codebook.rows;
Ptr<DescriptorMatcher> matcher = BFMatcher::create("BruteForce");
BOWImgDescriptorExtractor bow(akaze, matcher);
bow.setVocabulary(codebook);
try {
Mat img;
String imgName = "path_to_test_image";
img = imread(imgName, CV_LOAD_IMAGE_COLOR);
if (img.empty()){ //not image
cout << "bad" << endl;
}
else{
cout << "loaded" << endl;
resize(img, img, Size(200, 200));
Mat features;
vector<KeyPoint> keypoints;
akaze->detectAndCompute(img, noArray(), keypoints, features);
features.convertTo(features, CV_32F);
Mat bowFeatures;
vector<vector<int>> pointsIdxsOfCluster;
bow.compute(features, bowFeatures, &pointsIdxsOfCluster);
// bowFeatures is the descriptor you're looking for
// pointsIdxsOfCluster contains the indices of keypoints that belong to the cluster.
}
}
catch (int e){
cout << "An exception occurred. Nr. " << e << endl;
}
}
I am trying to implement face recognition using LDA with SIFT. I have an existing code of PCA with SIFT that uses SIFT to determine the keypoints and extract the descriptors and PCA to project those descriptors in the PCA sub-space. I am trying to achieve a similar functionality using LDA with SIFT.
I am trying to create an LDA object that will in turn call its member function 'project' but I get the following error:
OpenCV Error: Bad argument (The number of samples must equal the number of labels. Given 0 labels, 45 samples. ) in lda, file /home/shaurya/opencv-2.4.9/modules/contrib/src/lda.cpp, line 1015
terminate called after throwing an instance of 'cv::Exception'
what(): /home/mypath/opencv-2.4.9/modules/contrib/src/lda.cpp:1015: error: (-5) The number of samples must equal the number of labels. Given 0 labels, 45 samples. in function lda Aborted (core dumped)
The following is the PCA with SIFT code that I have executed:
#include <iostream>
#include <stdio.h>
#include <dirent.h>
#include <fstream>
#include <string>
#include <vector>
#include <iterator>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/nonfree/features2d.hpp>
#include <opencv2/features2d/features2d.hpp>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
if(argc != 3)
{
cout << "Usage: ./output <training database path> <test image>" << endl;
return -1;
}
// Reading training images paths
vector<string> namesTrainingImages;
vector<string>::iterator stringIt;
DIR *dir;
struct dirent *ent;
if ((dir = opendir (argv[1])) != NULL)
{
while ((ent = readdir (dir)) != NULL)
{
if((strcmp(ent -> d_name, ".") == 0) || (strcmp(ent -> d_name, "..") == 0))
{
continue;
}
string tempName(string(argv[1]) + string(ent -> d_name));
namesTrainingImages.push_back(tempName);
}
}
closedir(dir);
vector<Mat> trainingImages;
vector<Mat>::iterator imageIt;
// Reading training images
for(stringIt = namesTrainingImages.begin(); stringIt != namesTrainingImages.end(); ++stringIt)
{
Mat tempImage;
tempImage = imread(*stringIt, CV_LOAD_IMAGE_GRAYSCALE);
waitKey(5000);
if(!tempImage.data )
{
cout << "Could not open or find the image" << std::endl ;
continue;
}
else
{
trainingImages.push_back(tempImage);
}
}
vector< vector<KeyPoint> > keypoints;
vector<Mat> descriptor;
vector<Mat>::iterator descriptorIt;
SIFT sift;
double percentage = 0.95;
for(imageIt = trainingImages.begin(); imageIt != trainingImages.end(); ++imageIt)
{
vector<KeyPoint> tempKeypoints;
Mat tempDescriptor1, tempDescriptor2, tempDescriptor3;
// Generating keypoints and descriptors from training images
sift.operator()(*imageIt, *imageIt, tempKeypoints, tempDescriptor1, false);
keypoints.push_back(tempKeypoints);
// Using PCA to project and then backProject the descriptors of training images
PCA pca(tempDescriptor1, Mat(), CV_PCA_DATA_AS_ROW, percentage);
pca.PCA::project(tempDescriptor1, tempDescriptor2);
tempDescriptor3 = pca.PCA::backProject(tempDescriptor2);
descriptor.push_back(tempDescriptor3);
}
// Reading the test image
Mat testImage;
testImage = imread(argv[2], CV_LOAD_IMAGE_GRAYSCALE);
waitKey(5000);
if(!testImage.data)
{
cout << "Could not open or find the image" << std::endl ;
return -1;
}
vector<KeyPoint> testKeypoints;
Mat testDescriptor, testDescriptor1, testDescriptor2;
// Generating teh keypoints and the descriptor of the test image
sift.operator()(testImage, testImage, testKeypoints, testDescriptor1, false);
// Using PCA to project and then backProject the descriptor of the test image
PCA pca(testDescriptor1, Mat(), CV_PCA_DATA_AS_ROW, percentage);
pca.PCA::project(testDescriptor1, testDescriptor2);
testDescriptor = pca.PCA::backProject(testDescriptor2);
// Flann based matching to determine the best matching training image
FlannBasedMatcher matcher;
vector<DMatch> matches;
vector<DMatch> good_matches;
int goodMatchesCtr = -1, tempCtr = -1, ctr = -1;
for(descriptorIt = descriptor.begin(); descriptorIt != descriptor.end(); ++descriptorIt)
{
++tempCtr;
vector<DMatch> tempMatches;
vector<DMatch> temp_good_matches;
int tempGoodMatchesCtr = 0;
double min_dist = 100;
matcher.match(testDescriptor, *descriptorIt, tempMatches);
for(int i = 0; i < testDescriptor.rows && i < (*descriptorIt).rows; ++i)
{
double dist = tempMatches[i].distance;
if(dist < min_dist)
{
min_dist = dist;
}
}
for(int i = 0; i < testDescriptor.rows && i < (*descriptorIt).rows; ++i)
{
if(tempMatches[i].distance <= max(2 * min_dist, 0.02))
{
temp_good_matches.push_back(tempMatches[i]);
++tempGoodMatchesCtr;
}
}
if(tempGoodMatchesCtr > goodMatchesCtr)
{
goodMatchesCtr = tempGoodMatchesCtr;
matches = tempMatches;
good_matches = temp_good_matches;
ctr = tempCtr;
}
}
// Displaying the test image alongside the best matching training image
Mat img_matches;
drawMatches(testImage, testKeypoints, trainingImages[ctr], keypoints[ctr], good_matches, img_matches, Scalar ::all(-1), Scalar ::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
for( int i = 0; i < (int)good_matches.size(); ++i )
{
printf( "-- Good Match [%d] Keypoint 1: %d -- Keypoint 2: %d \n", i, good_matches[i].queryIdx, good_matches[i].trainIdx );
}
imshow("Good Matches", img_matches);
waitKey(0);
cout << "Executed!" << '\n';
return 0;
}
The following is the LDA with SIFT code that I am trying to execute:
#include <iostream>
#include <stdio.h>
#include <dirent.h>
#include <fstream>
#include <string>
#include <vector>
#include <iterator>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/nonfree/features2d.hpp>
#include <opencv2/features2d/features2d.hpp>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
if(argc != 3)
{
cout << "Usage: ./output <training database path> <test image>" << endl;
return -1;
}
// Reading training images paths
vector<string> namesTrainingImages;
vector<string>::iterator stringIt;
DIR *dir;
struct dirent *ent;
if ((dir = opendir (argv[1])) != NULL)
{
while ((ent = readdir (dir)) != NULL)
{
if((strcmp(ent -> d_name, ".") == 0) || (strcmp(ent -> d_name, "..") == 0))
{
continue;
}
string tempName(string(argv[1]) + string(ent -> d_name));
namesTrainingImages.push_back(tempName);
}
}
closedir(dir);
vector<Mat> trainingImages;
vector<Mat>::iterator imageIt;
// Reading training images
for(stringIt = namesTrainingImages.begin(); stringIt != namesTrainingImages.end(); ++stringIt)
{
Mat tempImage;
tempImage = imread(*stringIt, CV_LOAD_IMAGE_GRAYSCALE);
waitKey(5000);
if(!tempImage.data )
{
cout << "Could not open or find a training image" << std::endl ;
continue;
}
else
{
trainingImages.push_back(tempImage);
}
}
vector< vector<KeyPoint> > keypoints;
vector<Mat> descriptor;
vector<Mat>::iterator descriptorIt;
SIFT sift;
for(imageIt = trainingImages.begin(); imageIt != trainingImages.end(); ++imageIt)
{
vector<KeyPoint> tempKeypoints;
Mat tempDescriptor;
// Generating keypoints and descriptors from training images
sift.operator()(*imageIt, *imageIt, tempKeypoints, tempDescriptor, false);
keypoints.push_back(tempKeypoints);
// Trying to use LDA to project the descriptors of training images
LDA lda(tempDescriptor, Mat());
lda.LDA::project(tempDescriptor);
descriptor.push_back(tempDescriptor);
}
// Reading the test image
Mat testImage;
testImage = imread(argv[2], CV_LOAD_IMAGE_GRAYSCALE);
waitKey(5000);
if(!testImage.data)
{
cout << "Could not open or find the image" << std::endl ;
return -1;
}
vector<KeyPoint> testKeypoints;
Mat testDescriptor;
// Generating the keypoints and the descriptor of the test image
sift.operator()(testImage, testImage, testKeypoints, testDescriptor, false);
// Trying to use LDA to project the descriptor of the test image
LDA lda(testDescriptor, Mat());
lda.LDA::project(testDescriptor);
// Flann based matching to determine the best matching training image
FlannBasedMatcher matcher;
vector<DMatch> matches;
vector<DMatch> good_matches;
int goodMatchesCtr = -1, tempCtr = -1, ctr = -1;
for(descriptorIt = descriptor.begin(); descriptorIt != descriptor.end(); ++descriptorIt)
{
++tempCtr;
vector<DMatch> tempMatches;
vector<DMatch> temp_good_matches;
int tempGoodMatchesCtr = 0;
double min_dist = 100;
matcher.match(testDescriptor, *descriptorIt, tempMatches);
for(int i = 0; i < testDescriptor.rows && i < (*descriptorIt).rows; ++i)
{
double dist = tempMatches[i].distance;
if(dist < min_dist)
{
min_dist = dist;
}
}
for(int i = 0; i < testDescriptor.rows && i < (*descriptorIt).rows; ++i)
{
if(tempMatches[i].distance <= max(2 * min_dist, 0.02))
{
temp_good_matches.push_back(tempMatches[i]);
++tempGoodMatchesCtr;
}
}
if(tempGoodMatchesCtr > goodMatchesCtr)
{
goodMatchesCtr = tempGoodMatchesCtr;
matches = tempMatches;
good_matches = temp_good_matches;
ctr = tempCtr;
}
}
// Displaying the test image alogside the best matching training image
Mat img_matches;
drawMatches(testImage, testKeypoints, trainingImages[ctr], keypoints[ctr], good_matches, img_matches, Scalar ::all(-1), Scalar ::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
for( int i = 0; i < (int)good_matches.size(); ++i )
{
printf( "-- Good Match [%d] Keypoint 1: %d -- Keypoint 2: %d \n", i, good_matches[i].queryIdx, good_matches[i].trainIdx );
}
imshow("Good Matches", img_matches);
waitKey(0);
cout << "Executed!" << '\n';
return 0;
}
I write these programs on the gedit text editor and execute these programs on Ubuntu 12.04 with OpenCV 2.4.9.
EDIT: Basically I want a way to convert the below given lines of SIFT-PCA code into SIFT-LDA
PCA pca(testDescriptor1, Mat(), CV_PCA_DATA_AS_ROW, percentage);
pca.PCA::project(testDescriptor1, testDescriptor2);
testDescriptor = pca.PCA::backProject(testDescriptor2);
I tried to substitue the PCA constructor by the LDA constuctor in the following way:
LDA lda(testDescriptor, Mat());
lda.LDA::project(testDescriptor);
But I got the above mentioned error. My guess is that I am passing incorrect arguments to the LDA constructor. I have already gone through the documentation of LDA class given here, but had no luck in finding my mistake.
Any help regarding the above problem will be appreciated.
Thanks in advance!
I'm trying to train SVM and use it inside HOGDescrpitor from OpenCV.
The xml file was succesfully generated and loaded by HOGDescriptor but when I try to detect some object, then assertion is occurred:
OpenCV Error: Assertion failed (dsize.area() || (inv_scale_x > 0 &&
inv_scale_y > 0)) in resize, file
/build/buildd/opencv-2.4.8+dfsg1/modules/imgproc/src/imgwarp.cpp, line
1825 terminate called after throwing an instance of
'tbb::captured_exception' what():
/build/buildd/opencv-2.4.8+dfsg1/modules/imgproc/src/imgwarp.cpp:1825:
error: (-215) dsize.area() || (inv_scale_x > 0 && inv_scale_y > 0) in
function resize
To implement SVM trainer I used hints from using OpenCV and SVM with images
Generated XML file has about 144Kbytes. For positive and negative samples I used images of size 64x128 (2000 for positive and 2000 for negative)
Parameter for SVM trainer:
CvSVMParams svmParams;
svmParams.svm_type = CvSVM::C_SVC;
svmParams.kernel_type = CvSVM::LINEAR;
svmParams.term_crit = cvTermCriteria( CV_TERMCRIT_ITER, 10000, 1e-6 );
Code for detection:
int main()
{
HOGDescriptor hog();
if(!hog.load("/home/bin/hogdescriptor.xml"))
{
std::cout << "Failed to load file!" << std::endl;
return -1;
}
VideoCapture cap(0);
if(!cap.isOpened())
{
std::cout << "Error opening camera!" << std::endl;
return 1;
}
Mat testImage;
while ((cvWaitKey(30) & 255) != 27)
{
cap >> testImage;
detectTest(hog, testImage);
imshow("HOG custom detection", testImage);
}
return EXIT_SUCCESS;
}
void showDetections(const vector<Rect>& found, Mat& imageData) {
for (const Rect& rect : found)
{
Point rectPoint1;
rectPoint1.x = rect.x;
rectPoint1.y = rect.y;
Point rectPoint2;
rectPoint2.x = rect.x + rect.width;
rectPoint2.y = rect.y + rect.height;
std::cout << "detection x: " << rect.x << ", y: " << rect.y << std::endl;
rectangle(imageData, rectPoint1, rectPoint2, Scalar(0, 255, 0));
}
}
void detectTest(const HOGDescriptor& hog, Mat& imageData)
{
std::cout << "Trying to detect" << std::endl;
vector<Rect> found;
int groupThreshold = 2;
Size padding(Size(32, 32));
Size winStride(Size(8, 8));
double hitThreshold = 0.; // tolerance
hog.detectMultiScale(imageData, found, hitThreshold, winStride, padding, 1.05, groupThreshold);
// hog.detectMultiScale(imageData, found);
std::cout << "Trying to show detections" << std::endl;
showDetections(found, imageData);
}
XML:
<?xml version="1.0"?>
<opencv_storage>
<my_svm type_id="opencv-ml-svm">
<svm_type>C_SVC</svm_type>
<kernel><type>LINEAR</type></kernel>
<C>1.</C>
<term_criteria><epsilon>2.2204460492503131e-16</epsilon>
<iterations>10000</iterations></term_criteria>
<var_all>8192</var_all>
<var_count>8192</var_count>
<class_count>2</class_count>
<class_labels type_id="opencv-matrix">
<rows>1</rows>
<cols>2</cols>
<dt>i</dt>
<data>
-1 1</data></class_labels>
<sv_total>1</sv_total>
<support_vectors>
<_>
-9.25376153e-05 -9.25376153e-05 -9.25376153e-05 -9.25376153e-05 ...and many, many...</_></support_vectors>
<decision_functions>
<_>
<sv_count>1</sv_count>
<rho>-1.</rho>
<alpha>
1.</alpha>
<index>
0</index></_></decision_functions></my_svm>
</opencv_storage>
Can someone explain me this assertion or maybe can provide some solution for this problem? I spent almost 3 days to fix this but without any success... Thanks in advance!
this is the closer what i got... still trying to use this xml
private static void buscar_hog_svm() {
if (clasificador == null) {
clasificador = new CvSVM();
clasificador.load(path_vectores);
}
Mat img_gray = new Mat();
//gray
Imgproc.cvtColor(imag, img_gray, Imgproc.COLOR_BGR2GRAY);
//Extract HogFeature
hog = new HOGDescriptor(
_winSize //new Size(32, 16)
, _blockSize, _blockStride, _cellSize, _nbins);
MatOfFloat descriptorsValues = new MatOfFloat();
MatOfPoint locations = new MatOfPoint();
hog.compute(img_gray,
descriptorsValues,
_winSize,
_padding, locations);
Mat fm = descriptorsValues;
System.out.println("tamano fm: " + fm.size());
//Classification whether data is positive or negative
float result = clasificador.predict(fm);
System.out.println("resultado= " + result);
}
if you have more clues, please share
When I run this program and adjust the slider multiple times bar the image appears different even though it is at the same slider position. If you try this code, move the slider from the minimum to maximum position back and forth several times and you can see a slight alteration to the image each time.
I have traced the point at which this happens to the line running the add function in my onProgram6Trackbar1 function. Removing it removes the variations between slide movements. Why is this happening?
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <string>
using namespace cv;
using namespace std;
#include <cmath>
class ProgramData {
public:
ProgramData() {
k1=0;
k2=0;
k3=0;
k4=0;
k5=0;
}
int k1;
int k2;
int k3;
int k4;
int k5;
Mat * source_U8C3;
Mat * temp1_U8C3;
Mat * temp2_U8C3;
Mat * temp3_U8C1;
Mat * temp4_U8C1;
Mat * temp5_U8C1;
Mat * temp6_U8C1;
Mat * temp7_U8C1;
vector<Mat> tempv1_U8C1;
vector<Mat> tempv2_U8C1;
Mat * output_U8C1;
Mat * output_U8C3;
Mat * dim1by1;
};
static void onProgram6Trackbar1(int v, void* vp) {
ProgramData * pd = (ProgramData *) vp;
*(pd->temp3_U8C1) = pd->tempv1_U8C1[2].clone();
inRange(*(pd->temp3_U8C1), pd->k1, 255, *(pd->temp4_U8C1));
bitwise_not(*(pd->temp4_U8C1), *(pd->temp5_U8C1));
bitwise_and(*(pd->temp5_U8C1), *(pd->temp3_U8C1), *(pd->temp6_U8C1));
bitwise_or(pd->temp6_U8C1, Scalar(pd->k1), pd->temp7_U8C1, pd->temp4_U8C1);
imshow( "Glare Reduction 4", *(pd->temp7_U8C1));
}
void program6(char * argv) {
ProgramData pd;
pd.k1 = 0;
Mat source = imread(argv, IMREAD_COLOR); // Read the file
pd.source_U8C3 = &source;
Size s( pd.source_U8C3->size().width / 1.3, pd.source_U8C3->size().height / 1.3 );
resize( *(pd.source_U8C3), *(pd.source_U8C3), s, 0, 0, CV_INTER_AREA );
pd.output_U8C3 = new Mat(pd.source_U8C3->rows,pd.source_U8C3->cols,pd.source_U8C3->type());
pd.output_U8C1 = new Mat(pd.source_U8C3->rows,pd.source_U8C3->cols,CV_8UC1);
//pd.temp1_U8C3 = new Mat(pd.source_U8C3->rows,pd.source_U8C3->cols,pd.source_U8C3->type());
pd.temp2_U8C3 = new Mat(pd.source_U8C3->rows,pd.source_U8C3->cols,pd.source_U8C3->type());
pd.temp3_U8C1 = new Mat(pd.source_U8C3->rows,pd.source_U8C3->cols,CV_8UC1);
pd.temp4_U8C1 = new Mat(pd.source_U8C3->rows,pd.source_U8C3->cols,CV_8UC1);
pd.temp5_U8C1 = new Mat(pd.source_U8C3->rows,pd.source_U8C3->cols,CV_8UC1);
pd.temp6_U8C1 = new Mat(pd.source_U8C3->rows,pd.source_U8C3->cols,CV_8UC1);
pd.temp7_U8C1 = new Mat(pd.source_U8C3->rows,pd.source_U8C3->cols,CV_8UC1);
pd.dim1by1 = new Mat(100,800,CV_8UC1);
cout << "source type = " << pd.source_U8C3->type() << endl;
if(! pd.source_U8C3->data ) { cout << "Could not open image" << std::endl; return;}
cvtColor(*(pd.source_U8C3), *(pd.temp2_U8C3), CV_BGR2HSV); // original to hsv
split(*(pd.temp2_U8C3), pd.tempv1_U8C1);
namedWindow( "Glare Reduction - Controls", WINDOW_AUTOSIZE ); // Create a window for display.
onProgram6Trackbar1(0,&pd);
createTrackbar("k1", "Glare Reduction - Controls", &(pd.k1), 255, &onProgram6Trackbar1, &pd);
imshow( "Glare Reduction - Controls", *(pd.dim1by1) ); // Show our image inside it.
waitKey(0); // Wait for a keystroke in the window
}
int main( int argc, char** argv )
{
program6("Blocks1.jpg");
}
Update 1:
New code posted below. I tried changing the code to not use any Mat pointers. Still does the exact same thing.
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <string>
using namespace cv;
using namespace std;
#include <cmath>
class ProgramData {
public:
ProgramData() {
k1=0;
}
int k1;
Mat source_U8C3;
Mat temp1_U8C3;
Mat temp2_U8C3;
Mat temp3_U8C1;
Mat temp4_U8C1;
Mat temp5_U8C1;
Mat temp6_U8C1;
Mat temp7_U8C1;
vector<Mat> tempv1_U8C1;
vector<Mat> tempv2_U8C1;
Mat output_U8C1;
Mat output_U8C3;
Mat dim1by1;
};
static void onProgram6Trackbar1(int v, void* vp) {
ProgramData * pd = (ProgramData *) vp;
pd->temp3_U8C1 = pd->tempv1_U8C1[2].clone();
inRange(pd->temp3_U8C1, Scalar(pd->k1), Scalar(255), pd->temp4_U8C1);
bitwise_not(pd->temp4_U8C1, pd->temp5_U8C1); // Note for monday, here does not work below works. Why?
bitwise_and(pd->temp5_U8C1, pd->temp3_U8C1, pd->temp6_U8C1);
bitwise_or(pd->temp6_U8C1, Scalar(pd->k1), pd->temp7_U8C1, pd->temp4_U8C1);
imshow( "Glare Reduction 4", pd->temp7_U8C1);
}
int main( int argc, char** argv ) {
ProgramData pd;
pd.k1 = 0;
pd.source_U8C3 = imread("Photo Examples/Blocks1.jpg", IMREAD_COLOR); // Read the file
Size s( pd.source_U8C3.size().width / 1.3, pd.source_U8C3.size().height / 1.3 );
resize( pd.source_U8C3, pd.source_U8C3, s, 0, 0, CV_INTER_AREA );
pd.dim1by1.create(100,800,CV_8UC1);
cout << "source type = " << pd.source_U8C3.type() << endl;
if(! pd.source_U8C3.data ) { cout << "Could not open image" << std::endl; return 0;}
cvtColor(pd.source_U8C3, pd.temp2_U8C3, CV_BGR2HSV); // original to hsv
split(pd.temp2_U8C3, pd.tempv1_U8C1);
namedWindow( "Glare Reduction - Controls", WINDOW_AUTOSIZE ); // Create a window for display.
onProgram6Trackbar1(0,&pd);
createTrackbar("k1", "Glare Reduction - Controls", &(pd.k1), 255, &onProgram6Trackbar1, &pd);
imshow( "Glare Reduction - Controls", pd.dim1by1 ); // Show our image inside it.
waitKey(0); // Wait for a keystroke in the window
return 0;
}
Update 2:
I think I may have found the source of the problem. When add this line
static void onProgram6Trackbar1(int v, void* vp) {
ProgramData * pd = (ProgramData *) vp;
pd->temp3_U8C1 = pd->tempv1_U8C1[2].clone();
inRange(pd->temp3_U8C1, Scalar(pd->k1), Scalar(255), pd->temp4_U8C1);
bitwise_not(pd->temp4_U8C1, pd->temp5_U8C1);
bitwise_and(pd->temp5_U8C1, pd->temp3_U8C1, pd->temp6_U8C1);
pd->temp7_U8C1 = pd->tempv1_U8C1[2].clone(); // <----
bitwise_or(pd->temp6_U8C1, Scalar(pd->k1), pd->temp7_U8C1, pd->temp4_U8C1);
imshow( "Glare Reduction 4", pd->temp7_U8C1);
}
to onProgram6Trackbar1 it suddenly works as expected. I thought since opencv 2 does its own memory allocation I didn't have to initialize pd->temp7_U8C1 which is serving as the output matrix in the call to bitwise_or. It's almost like the underlying memory in pd->temp7_U8C1 was pointing to memory that belonged to one of the buffers that was used as output to the image processing done in main (pd.tempv1_U8C1 or pd.source_U8C3). Either the line I added did something else that I have not thought of.
So my new question is why did this line fix it and what is going on underneath. Is the result of using an uninitialized mat behavior defined somewhere in the documentation? It was my understanding that you don't have to initialize the size or type of a matrix that you are using as an output mat.
maybe a bit too old, anyway: First check the slightly cleaned code. I removed everything that's redundant and send the actual function of the trackbar into a member of your class. This way, you can directly operate on the members.
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;
class ProgramData
{
public:
ProgramData()
{
k1 = 0;
}
int k1;
Mat source_U8C3,
temp2_U8C3, temp4_U8C1,
temp5_U8C1, temp6_U8C1,
temp7_U8C1;
vector<Mat> tempv1_U8C1;
void reduce_glare(void)
{
// sets elements in temp4 to 255 if within range
inRange(tempv1_U8C1[2], Scalar(k1), Scalar(255), temp4_U8C1);
// bitwise_not(InputArray src, OutputArray dst)
bitwise_not(temp4_U8C1, temp5_U8C1);
// bitwise_and(InputArray src1, InputArray src2, OutputArray dst)
bitwise_and(temp5_U8C1, tempv1_U8C1[2], temp6_U8C1);
// watch out here:
temp7_U8C1 = Mat::ones(tempv1_U8C1[2].size(), CV_8UC1);
Mat x = Mat::ones(tempv1_U8C1[2].size(), CV_8UC1) * k1;
// bitwise_or(InputArray src1, InputArray src2, OutputArray dst, InputArray mask)
bitwise_or(temp6_U8C1, x, temp7_U8C1, temp4_U8C1);
cout << "source type = " << temp7_U8C1.type() << endl;
cout << "source channels = " << temp7_U8C1.channels() << endl;
cout << "source depth = " << temp7_U8C1.depth() << endl;
}
};
void onProgram6Trackbar1(int v, void *vp)
{
ProgramData *pd = static_cast<ProgramData *>(vp);
(*pd).reduce_glare();
imshow("Glare Reduction 4", pd->temp7_U8C1);
}
int main(int argc, char **argv)
{
ProgramData pd;
pd.source_U8C3 = imread("CutDat.jpeg", IMREAD_COLOR);
Size s(pd.source_U8C3.size().width / 1.3, pd.source_U8C3.size().height / 1.3);
resize(pd.source_U8C3, pd.source_U8C3, s, 0, 0, CV_INTER_AREA);
cout << "source type = " << pd.source_U8C3.type() << endl;
cvtColor(pd.source_U8C3, pd.temp2_U8C3, CV_BGR2HSV);
split(pd.temp2_U8C3, pd.tempv1_U8C1);
namedWindow("Glare Reduction - Controls", WINDOW_AUTOSIZE);
imshow("Glare Reduction - Controls", Mat(100, 800, CV_8UC1));
createTrackbar("k1", "Glare Reduction - Controls", &(pd.k1), 255, &onProgram6Trackbar1, &pd);
waitKey(0);
return 0;
}
Important is the line where temp7_U8C1 is initialized, but not with the original data. The result you get is still not want you want, but it highlights that the issue is within the call to bitwise_or. Your question regarding the Scalar bug doesn't apply here as I've shown it in the code.
The code is tested on Windows with 2.4.10 and on Ubuntu 2.4.8 both giving the same results. Testing the code on valgrind runs fine.