I'm trying to find corners in my image by Harris Detector, but I have a problem when i run this code:
int blockSize = 2;
int apertureSize = 3;
double k = 0.04;
IplImage* binMaxMatchContourImage = cvCreateImage( cvGetSize(maxMatchContourImage), 8, 1);
IplImage* afterHarrisImage = cvCreateImage( cvGetSize(maxMatchContourImage), 8, 1);
cvCanny(maxMatchContourImage, binMaxMatchContourImage, 50, 200);
cvCornerHarris( binMaxMatchContourImage, afterHarrisImage, blockSize, apertureSize, k);
But my program failed:
OpenCV Error: Bad argument (Unknown array type) in unknown function, file ..\..\..\src\opencv\modules\core\src\matrix.cpp, line 698
Please, explain me, where is my problem?
Check whether maxMatchContourImage is of the same type and size as maxMatchContourImage. Both should be single channel images for Canny edge detection to work.
If this condition is met, cvCornerHarris should work.
Related
My kmeans() function is failing with the error:
OpenCV Error: Assertion failed (N >= K) in cv::kmeans, file C:\builds\master_Pac
kSlave-win32-vc12-shared\opencv\modules\core\src\kmeans.cpp, line 231
Whats my error? 'N >= K' must mean its checking whether the Mat rows*cols(length) is > clusters - which mine is (I think). My Mat has 1 row with around 80k columns. Is my Mat that I am passing as the first parameter (for kmeans) empty of pixel/voxel data? I have confirmed that this parameter is a 'collapsed' image (1 row, 80K columns). So its not quite empty but it could all that it's all black pixels which may be the error?
Mat image = imread("images/jp.png", CV_32F); // The Jurassic Park movie logo
cvtColor(image, image, CV_BGR2RGB);
Mat collapsedImage = image.reshape(1, 1);
collapsedImage.convertTo(collapsedImage, CV_32F);
int clusterCount = 2;
Mat labels, centres;
// Assertion error thrown here
kmeans(collapsedImage, clusterCount, labels,
TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 1.0),
3, KMEANS_PP_CENTERS, centres);
imshow("flat", collapsedImage); // shows long flat with all black pixels
imshow("image", image);
Ok looks like the problem was my reshaping. It should be:
Mat collapsedImage = image.reshape(1, image.rows * image.cols);
I am attempting to calculate a histogram of a ROI in order to find that ROI in an image using back projection. My code is
cvtColor(frame, hsvFrame, CV_BGR2HSV);
cvtColor(ROI, hsvROI, CV_BGR2HSV);
float hRanges[] = {0, 180};
float sRanges[] = {0, 256};
float vRanges[] = {0, 256};
const float* ranges[] = { hRanges, sRanges, vRanges};
int histSize = 256;
int channels[] = {0,1,2};
calcHist(&hsvROI, 1, channels, Mat(), ROIhist, 3, &histSize, ranges);
calcBackProject(&hsvFrame, 1, channels, ROIhist, backProj, ranges, true);
imshow("display", backProj);
Firstly, please assume all Mats have already been declared (this is only a snippet). In my understanding, the more dimensions/channels I use the more accurate the back projection should be...so i have decided to include all 3 channels of an HSV row, and therefore of course an HSV image (is this necessary? is there a better way?). In this example above, i get the error:
OpenCV Error: Assertion failed (s >= 0) in setSize, file opencv/modules/core/src/matrix.cpp, line 293
libc++abi.dylib: terminating with uncaught exception of type cv::Exception: opencv/modules/core/src/matrix.cpp:293: error: (-215) s >= 0 in function setSize
which gets triggered on the CalcHist line. My solution was to make sure ROIhist is of the same size as hsvROI, so I then put this line just before I declare the ranges:
Mat ROIhist(hsvROI.rows,hsvROI.cols, CV_8UC3, Scalar(0,0,0));
I think it worked, as on the next run, i got a different error that was triggered on the CalcBackProject line:
OpenCV Error: Assertion failed (dims > 0 && !hist.empty()) in calcBackProject, file /opencv/modules/imgproc/src/histogram.cpp, line 1887
libc++abi.dylib: terminating with uncaught exception of type cv::Exception: opencv/modules/imgproc/src/histogram.cpp:1887: error: (-215) dims > 0 && !hist.empty() in function calcBackProject
Which i really do not understand. In fact I also feel like my previous fix by adding the Mat constructor shouldn't be necessary anyway...?
I essentially need to be able to calculate this back projection as accurately as possible while using both functions in ideally a rather simple and standard way. My attempt clearly has some logic flaw somewhere and I would appreciate an explanation or suggestion to how i should go about this properly to get the best results. Thanks in advance !
histSize in your case should be the number of bins in your 3D histogram (so an int array, not just an int). And I'd use lower numbers for them, so that more pixels would manage to fall into one bin, and would make your backprojection more meaningful:
int histSize[] = {32, 32, 32};
...
calcHist(&hsvROI, 1, channels, Mat(), ROIhist, 3, histSize, ranges);
im learning about SVM, so im making a sample program that trains an SVM to detect if a symbol is in an image or if its not. All the images are black and white (the symbols would be black and the background white). I have 12 training images, 6 positives (with the symbol) and 6 negatives (without it). Im using hu moments to get the descriptors of every image and then i construct the training matrix with those descriptors. also i have a Labels matrix, which contains a label for each image: 1 if its positive and 0 if its negative. but im getting an error (something like a segmentation fault) at the line where i train the SVM. here is my code:
using namespace cv;
using namespace std;
int main(int argc, char* argv[])
{
//arrays where the labels and the features will be stored
float labels[12] ;
float trainingData[12][7] ;
Moments moment;
double hu[7];
//===============extracting the descriptos for each positive image=========
for ( int i = 0; i <= 5; i++){
//the images are called t0.png ... t5.png and are in the folder train
std::string path("train/t");
path += std::to_string(i);
path += ".png";
Mat input = imread(path, 0); //read the images
bitwise_not(input, input); //invert black and white
Mat BinaryInput;
threshold(input, BinaryInput, 100, 255, cv::THRESH_BINARY); //apply theshold
moment = moments(BinaryInput, true); //calculate the moments of the current image
HuMoments(moment, hu); //calculate the hu moments (this will be our descriptor)
//setting the row i of the training data as the hu moments
for (int j = 0; j <= 6; j++){
trainingData[i][j] = (float)hu[j];
}
labels[i] = 1; //label=1 because is a positive image
}
//===============extracting the descriptos for each negative image=========
for (int i = 0; i <= 5; i++){
//the images are called tn0.png ... tn5.png and are in the folder train
std::string path("train/tn");
path += std::to_string(i);
path += ".png";
Mat input = imread(path, 0); //read the images
bitwise_not(input, input); //invert black and white
Mat BinaryInput;
threshold(input, BinaryInput, 100, 255, cv::THRESH_BINARY); //apply theshold
moment = moments(BinaryInput, true); //calculate the moments of the current image
HuMoments(moment, hu); //calculate the hu moments (this will be our descriptor)
for (int j = 0; j <= 6; j++){
trainingData[i + 6][j] = (float)hu[j];
}
labels[i + 6] = 0; //label=0 because is a negative image
}
//===========================training the SVM================
//we convert the labels and trainingData matrixes to Mat objects
Mat labelsMat(12, 1, CV_32FC1, labels);
Mat trainingDataMat(12, 7, CV_32FC1, trainingData);
//create the SVM
Ptr<ml::SVM> svm = ml::SVM::create();
//set the parameters of the SVM
svm->setType(ml::SVM::C_SVC);
svm->setKernel(ml::SVM::LINEAR);
CvTermCriteria criteria = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);
svm->setTermCriteria(criteria);
//Train the SVM !!!!!HERE OCCURS THE ERROR!!!!!!
svm->train(trainingDataMat, ml::ROW_SAMPLE, labelsMat);
//Testing the SVM...
Mat test = imread("train/t1.png", 0); //this should be a positive test
bitwise_not(test, test);
Mat testBin;
threshold(test, testBin, 100, 255, cv::THRESH_BINARY);
Moments momentP = moments(testBin, true); //calculate the moments of the test image
double huP[7];
HuMoments(momentP, huP);
Mat testMat(1, 7, CV_32FC1, huP); //setting the hu moments to the test matrix
double resp = svm->predict(testMat); //pretiction of the SVM
printf("%f", resp); //Response
getchar();
}
i know that the program is running fine until that line because i printed labelsMat and trainingDataMat and the values inside them are ok. Even in the console i can see that the program is running fine until that exact line executes. the console then shows this message:
OpenCV error: Bad argument (in the case of classification problem the responses must be categorical; either specify varType when creating TrainDatam or pass integer responses)
i dont really know what this means. any idea of what could be causing the problem? if you need any other details please tell me.
EDIT
for future readers:
the problem was in the way i defined the labels array as an array of float and the LabelsMat as a Mat of CV_32FC1. the array that contains the labels needs to have integers inside, so i changed:
float labels[12];
to
int labels[12];
and also changed
Mat labelsMat(12, 1, CV_32FC1, labels);
to
Mat labelsMat(12, 1, CV_32SC1, labels);
and that solved the error. Thank you
Trying changing:
Mat labelsMat(12, 1, CV_32FC1, labels);
to
Mat labelsMat(12, 1, CV_32SC1, labels);
From: http://answers.opencv.org/question/63715/svm-java-opencv-3/
If that doesn't work, hopefully one of these posts will help you:
Opencv 3.0 SVM train classification issues
OpenCV SVM Training Data
I'm trying to use OpenCV to train a neural network in C++.
I can't convert between cv::Mat* (or Mat*, if namespace cv is used) to CvMat*, and I would appreciate some help with this.
Let me elaborate:
I've got two data structures of cv::Mat* type. The first is the set of feature vectors and the second is the set of expected output.
cv::Mat *feat = new cv::Mat(3000, 100, CV_32F, featureData);
cv::Mat *op = new cv::Mat(3000, 2, CV_32F, expectedOutput);
(These are 3000 data points of feature vector length = 100 and output state = 2)
These two matrices had been populated with data of correct dimensions and seem to be working fine when sample data were printed on the console.
The neural network has been initialized as:
int layers_array[] = {100,200,2}; //hidden layer nodes = 200
CvMat* layer = cvCreateMatHeader(1, 3, CV_32SC1);
cvInitMatHeader(layer, 1,3,CV_32SC1, layers_array);
CvANN_MLP nnetwork;
nnetwork.create(layer, CvANN_MLP::SIGMOID_SYM, SIGMOID_ALPHA, SIGMOID_BETA);
Now, the train method of ANN is of the following template:
virtual int train( const CvMat* inputs, const CvMat* outputs,
const CvMat* sampleWeights, const CvMat* sampleIdx=0,
CvANN_MLP_TrainParams params = CvANN_MLP_TrainParams(),
int flags=0 );
I tried to convert between cv::Mat * and CvMat * using the following code:
CvMat featMat,opMat;
(&featMat)->cols = feat->cols;
(&featMat)->rows = feat->rows;
(&featMat)->type = CV_32F;
(&featMat)->data.fl = (float *)feat->data;
(&opMat)->cols = op->cols;
(&opMat)->rows = op->rows;
(&opMat)->type = CV_32F;
(&opMat)->data.fl = (float *)op->data;
//setting up the ANN training parameters
int iterations = network.train(&featMat, &opMat, NULL, NULL, trainingParams);
When I run this code, I get the following error message in my console:
**OpenCV Error: Bad argument (input training data should be a floating-point matrix withthe number of rows equal to the number of training samples and the number
of columns equal to the size of 0-th (input) layer) in CvANN_MLP::prepare_to_train, file ..\..\OpenCV-2.3.0-win-src\OpenCV-2.3.0\modules\ml\src\ann_mlp.cpp,
line 694**
I understand the error message. However, to the best of my knowledge, I believe I haven't made a mess of the number of nodes in the input/output layer.
Can you please help me understand what is going wrong?
please try to avoid pointers to cv::Mat as well as CvMat* in general.
luckily, there's an overload to CvANN_MLP::train that takes cv::Mat as args, so use that instead:
cv::Mat feat = cv::Mat(3000, 100, CV_32F, featureData);
cv::Mat op = cv::Mat(3000, 2, CV_32F, expectedOutput);
int layers_array[] = {100,200,2}; //hidden layer nodes = 200
cv::Mat layers = cv::Mat (3, 1, CV_32SC1, layers_array );
CvANN_MLP nnetwork;
nnetwork.create(layers, CvANN_MLP::SIGMOID_SYM, SIGMOID_ALPHA, SIGMOID_BETA);
int iterations = nnetwork.train(feat, op, cv::Mat(), cv::Mat(), CvANN_MLP_TrainParams());
I am trying to run kmeans on a 3 channel color image, but every time I try to run the function it seems to crash with the following error:
OpenCV Error: Assertion failed (data.dims <= 2 && type == CV_32F && K > 0) in unknown function, file ..\..\..\OpenCV-2.3.0\modules\core\src\matrix.cpp, line 2271
I've included the code below with some comments to help specify what is being passed in. Any help is greatly appreciated.
// Load in an image
// Depth: 8, Channels: 3
IplImage* iplImage = cvLoadImage("C:/TestImages/rainbox_box.jpg");
// Create a matrix to the image
cv::Mat mImage = cv::Mat(iplImage);
// Create a single channel image to create our labels needed
IplImage* iplLabels = cvCreateImage(cvGetSize(iplImage), iplImage->depth, 1);
// Convert the image to grayscale
cvCvtColor(iplImage, iplLabels, CV_RGB2GRAY);
// Create the matrix for the labels
cv::Mat mLabels = cv::Mat(iplLabels);
// Create the labels
int rows = mLabels.total();
int cols = 1;
cv::Mat list(rows, cols, mLabels .type());
uchar* src;
uchar* dest = list.ptr(0);
for(int i=0; i<mLabels.size().height; i++)
{
src = mLabels.ptr(i);
memcpy(dest, src, mLabels.step);
dest += mLabels.step;
}
list.convertTo(list, CV_32F);
// Run the algorithm
cv::Mat labellist(list.size(), CV_8UC1);
cv::Mat centers(6, 1, mImage.type());
cv::TermCriteria termcrit(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0);
kmeans(mImage, 6, labellist, termcrit, 3, cv::KMEANS_PP_CENTERS, centers);
The error says all: Assertion failed (data.dims <= 2 && type == CV_32F && K > 0)
These are very simple rules to understand, the function will work only if:
mImage.depth() is CV_32F
if mImage.dims is <= 2
and if K > 0. In this case, you define K as 6.
From what you stated on the question, it seems that:
IplImage* iplImage = cvLoadImage("C:/TestImages/rainbox_box.jpg");`
is loading the image as IPL_DEPTH_8U by default and not IPL_DEPTH_32F. This means that mImage is also IPL_DEPTH_8U, which is why your code is not working.