OpenCv - Assertion failed in svm train - c++

I can find why i this happening. I have 5 classes and made labels and trainData but it gives assertion failed. Why? Labels are 1x1x884 ( i tried 1x884x1 also, it is the same ), and fmat 1 x 884 x 680400 , all float32. Error is :
and code:
HOGDescriptor hog;
vector<vector< float>> features;
int labels[884] = {};
int brojac = 0;
cv::String path1("C:/Users/Kristina/Desktop/Kompjuterska vizija/PrviProjekat/PrviProjekat/Chihuahua/*.jpg"); //select only jpg
vector<cv::String> fn;
vector<cv::Mat> data;
cv::glob(path1, fn, true); // recurse
for (size_t k = 0; k<fn.size(); ++k)
{
cv::Mat im = cv::imread(fn[k]);
if (im.empty()) continue; //only proceed if sucsessful
// you probably want to do some preprocessing
cvtColor(im, im, CV_RGB2GRAY);
resize(im, im, Size(200, 200));//resize image
vector< float> descriptorsValues;
hog.compute(im, descriptorsValues);
features.push_back(descriptorsValues);
labels[brojac] = 1;
brojac++;
data.push_back(im);
}
cv::String path2("C:/Users/Kristina/Desktop/Kompjuterska vizija/PrviProjekat/PrviProjekat/ShihTzu/*.jpg"); //select only jpg
vector<cv::String> fn2;
vector<cv::Mat> data2;
cv::glob(path2, fn2, true); // recurse
for (size_t k = 0; k<fn2.size(); ++k)
{
cv::Mat im = cv::imread(fn2[k]);
vector< float> descriptorsValues;
if (im.empty()) continue; //only proceed if sucsessful
// you probably want to do some preprocessing
cvtColor(im, im, CV_RGB2GRAY);
resize(im, im, Size(200, 200));//resize image
hog.compute(im, descriptorsValues);
features.push_back(descriptorsValues);
labels[brojac] = 2;
brojac++;
data.push_back(im);
}
cv::String path3("C:/Users/Kristina/Desktop/Kompjuterska vizija/PrviProjekat/PrviProjekat/Yorkshireterrier/*.jpg"); //select only jpg
vector<cv::String> fn3;
vector<cv::Mat> data3;
cv::glob(path3, fn3, true); // recurse
for (size_t k = 0; k<fn3.size(); ++k)
{
vector< float> descriptorsValues;
cv::Mat im = cv::imread(fn3[k]);
if (im.empty()) continue; //only proceed if sucsessful
// you probably want to do some preprocessing
cvtColor(im, im, CV_RGB2GRAY);
resize(im, im, Size(200, 200));//resize image
hog.compute(im, descriptorsValues);
features.push_back(descriptorsValues);
labels[brojac] = 3;
brojac++;
data.push_back(im);
}
cv::String path4("C:/Users/Kristina/Desktop/Kompjuterska vizija/PrviProjekat/PrviProjekat/vizsla/*.jpg"); //select only jpg
vector<cv::String> fn4;
vector<cv::Mat> data4;
cv::glob(path4, fn4, true); // recurse
for (size_t k = 0; k<fn4.size(); ++k)
{
cv::Mat im = cv::imread(fn4[k]);
vector< float> descriptorsValues;
if (im.empty()) continue; //only proceed if sucsessful
// you probably want to do some preprocessing
cvtColor(im, im, CV_RGB2GRAY);
resize(im, im, Size(200, 200));//resize image
hog.compute(im, descriptorsValues);
features.push_back(descriptorsValues);
labels[brojac] = 4;
brojac++;
data.push_back(im);
}
cv::String path5("C:/Users/Kristina/Desktop/Kompjuterska vizija/PrviProjekat/PrviProjekat/pug/*.jpg"); //select only jpg
vector<cv::String> fn5;
vector<cv::Mat> data5;
cv::glob(path5, fn5, true); // recurse
for (size_t k = 0; k<fn5.size(); ++k)
{
cv::Mat im = cv::imread(fn5[k]);
vector< float> descriptorsValues;
if (im.empty()) continue; //only proceed if sucsessful
// you probably want to do some preprocessing
cvtColor(im, im, CV_RGB2GRAY);
resize(im, im, Size(200, 200));//resize image
hog.compute(im, descriptorsValues);
features.push_back(descriptorsValues);
labels[brojac] = 5;
brojac++;
data.push_back(im);
}
Mat labelsMat(884, 1, CV_32FC1, labels);
Mat fmat(features[0].size(), features.size(), CV_32FC1, features.data());
Ptr<SVM> svm = SVM::create();
svm->setType(SVM::C_SVC);
svm->setKernel(SVM::LINEAR);
svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));
svm->train(fmat, ml::SampleTypes::ROW_SAMPLE, labelsMat);

Related

OpenCV Error: Camera Calibration: Assertion failed in matrix_wrap.cpp

The Error:
OpenCV(3.4.1) Error: Assertion failed (i < 0) in cv::debug_build_guard::_InputArray::getMat_,
file C:\build\master_winpack-build-win64-vc15\opencv\modules\core\src\matrix_wrap.cpp, line 50
The Code inside "matrix_wrap.cpp" that triggers the Error:
if( k == STD_VECTOR )
{
CV_Assert( i < 0 );
int t = CV_MAT_TYPE(flags);
const std::vector<uchar>& v = *(const std::vector<uchar>*)obj;
return !v.empty() ? Mat(size(), t, (void*)&v[0]) : Mat();
}
Entire Code:
#include <iostream>
#include <opencv2/opencv.hpp>
int main(int argc, char *argv[])
{
cv::Mat img = cv::imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
cv::Size imageSize = cv::Size(img.size[0], img.size[1]);
cv::Mat cameraMatrix, distCoeffs;
double squareSize = 30;
cv::Size boardSize = cv::Size(6, 11);
std::vector<cv::Point2f> imagePoints;
std::vector<cv::Point3f> objectPoints;
for (int i = 0; i < boardSize.height; i++) {
for (int j = 0; j < boardSize.width; j++) {
objectPoints.push_back(
cv::Point3f(float(j * squareSize), float(i * squareSize), 0));
}
}
std::vector<cv::Mat> rvecs, tvecs;
bool found = false;
if (img.size[0] > 1)
{
bool found = findChessboardCorners(img, boardSize, imagePoints, cv::CALIB_CB_ADAPTIVE_THRESH);
if (found)
{
drawChessboardCorners(img, boardSize, imagePoints, found);
}
objectPoints.resize(imagePoints.size(), objectPoints[0]);
double rms = calibrateCamera(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs);
cv::namedWindow("My Image");
cv::imshow("My Image", img);
cv::waitKey(1000);
}
return 0;
}
I want to use a basic camera calibration with a straigth chessboard.
Until the function "calibrateCamera" everything works fine, but I can't figure out why this Error shows up.
The size of "objectPoints" and "imagePoints" is the same.
Thank you in advance.
P.S.:
I'm new in this forum and also in OpenCV ;)
As per this source of opencv, lines 3139 and 3142 :
CV_Error(CV_StsUnsupportedFormat, "objectPoints should contain vector of vectors of points of type Point3f");
CV_Error(CV_StsUnsupportedFormat, "imagePoints1 should contain vector of vectors of points of type Point2f");
the types for objectPoints and imagePoints should be std::vector<std::vector<Point{2|3}f>>

opencv find homography using feature matching

I am calculating homography with reference here.
http://docs.opencv.org/2.4/doc/tutorials/features2d/feature_homography/feature_homography.html
However, there is an error even though it is a reference code.
The min_dist value is always 0, so the size of good_matches is 0, in the code.
What is wrong and how can we solve it?
int main(int argc, char **argv)
{
cv::VideoCapture cam(0);
cv::Mat img(480, 640, CV_8UC3, cv::Scalar(0, 0, 0));
cv::Mat img2(480, 640, CV_8UC3, cv::Scalar(0, 0, 0));
cv::Ptr<cv::AKAZE> akaze = cv::AKAZE::create();
std::vector<cv::KeyPoint> kp;
cv::Mat descr;
while (1)
{
cam >> img;
cv::Mat aka;
akaze->detectAndCompute(img, cv::noArray(), kp, descr);
cv::drawKeypoints(img, kp, aka);
cv::imshow("AKAZE", aka);
if (cv::waitKey(10) == 's')
{
break;
}
kp.clear();
}
akaze.release();
std::vector<cv::KeyPoint> kp_query;
cv::Mat descr_query;
cv::Ptr<cv::AKAZE> akaze2 = cv::AKAZE::create();
while (1)
{
cv::Mat aka;
cam >> img2;
akaze2->detectAndCompute(img2, cv::noArray(), kp_query, descr_query);
cv::BFMatcher matcher(cv::NORM_HAMMING);
std::vector<cv::DMatch> matches;
matcher.match(descr_query, descr, matches);
double max_dist = 0, min_dist = 100.0;
for (int i = 0; i<descr_query.rows; i++)
{
double dist = matches[i].distance;
if (dist < min_dist) min_dist = dist;
if (dist > max_dist) max_dist = dist;
}
printf("-- Max dist : %f \n", max_dist);
printf("-- Min dist : %f \n", min_dist);
std::vector<cv::DMatch> good_matches;
for (int i = 0; i<descr_query.rows; i++)
{
if (matches[i].distance < 3 * min_dist)
good_matches.push_back(matches[i]);
}
std::vector<cv::Point2f> train, query;
for (int i = 0; i<good_matches.size(); i++)
{
train.push_back(kp[good_matches[i].queryIdx].pt);
query.push_back(kp_query[good_matches[i].trainIdx].pt);
}
cv::Mat output_mask;
cv::Mat H = cv::findHomography(train, query, CV_RANSAC, 3, output_mask);
cv::Mat m;
cv::drawMatches(img, kp, img2, kp_query, good_matches, m, cv::Scalar::all(-1), cv::Scalar::all(-1),
std::vector<char>(), cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
cv::imshow("match", m);
cv::drawKeypoints(img2, kp_query, aka);
cv::waitKey(10);
kp_query.clear();
}
}
So far, I could't see any wrong procedure in your code, But you have 3 Channel 8-Bit Image there. Try to use a 1 Channel 8-Bit Image, because that is the format of the Images in your linked tutorial. So try changing cv::Mat img2(480, 640, CV_8UC3, cv::Scalar(0, 0, 0)); to cv::Mat img2(480, 640, CV_8UC1, cv::Scalar(0, 0, 0)); For both images. If this is not working for cam >> img then you have to try to convert image to CV_8UC1 after you read it from your cam.

Find good keypoints match code

I found this code inside LATCH_match.cpp in xfeature2D folder:
BFMatcher matcher(NORM_HAMMING);
vector< vector<DMatch> > nn_matches;
matcher.knnMatch(desc1, desc2, nn_matches, 2);
vector<KeyPoint> matched1, matched2, inliers1, inliers2;
vector<DMatch> good_matches;
for (unsigned i = 0; i < matched1.size(); i++) {
Mat col = Mat::ones(3, 1, CV_64F);
col.at<double>(0) = matched1[i].pt.x;
col.at<double>(1) = matched1[i].pt.y;
col = homography * col;
col /= col.at<double>(2);
double dist = sqrt(pow(col.at<double>(0) - matched2[i].pt.x, 2) +
pow(col.at<double>(1) - matched2[i].pt.y, 2));
if (dist < inlier_threshold) {
int new_i = static_cast<int>(inliers1.size());
inliers1.push_back(matched1[i]);
inliers2.push_back(matched2[i]);
good_matches.push_back(DMatch(new_i, new_i, 0));
}
}
Mat res;
drawMatches(img1, inliers1, img2, inliers2, good_matches, res);
imwrite("latch_res.png", res);
I see that this a kind of ratio test, but I don't get what's the point of inliers and homography

Crop Triangle with opencv c++

User,
I want to crop that Triangle on the image and show it in another window with opencv c++. I know all three Coordinates.
Can anyone help me? I did not find any answer on the Internet about "triangle cropping". Thanks!
EDIT: The Problem here is that i cannot use ROI for cropping the Triangle. I have to copy just the triangle without any background or something around. Is it possible to create my own ROI by knowing the Coordinates of the triangle [p1(302,179), p2(329,178), p3(315,205)]?
cv::Mat inputImage = cv::imread("input.png");
if (inputImage.channels() > 1)
{
cv::cvtColor(inputImage, inputImage, CV_RGB2GRAY);
}
// replace these values with your actual coordinates
// I found these by first saving your provided image, then
// using Microsoft Paint
int x0 = 242;
int y0 = 164;
int x1 = 314;
int y1 = 38;
int x2 = 387;
int y2 = 164;
// then create a line masking using these three points
cv::Mat lineMask = cv::Mat::zeros(inputImage.size(), inputImage.type());
cv::line(lineMask, cv::Point(x0, y0), cv::Point(x1, y1), cv::Scalar(255, 255, 0), 1, 8, 0);
cv::line(lineMask, cv::Point(x0, y0), cv::Point(x2, y2), cv::Scalar(255, 255, 0), 1, 8, 0);
cv::line(lineMask, cv::Point(x1, y1), cv::Point(x2, y2), cv::Scalar(255, 255, 0), 1, 8, 0);
// perform contour detection on your line mask
cv::vector<cv::vector<cv::Point>> contours;
cv::vector<cv::Vec4i> hierarchy;
cv::findContours(lineMask, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0));
// calculate the distance to the contour
cv::Mat raw_dist(lineMask.size(), CV_32FC1);
for (int i = 0; i < lineMask.rows; i++)
{
for (int j = 0; j < lineMask.cols; j++)
{
raw_dist.at<float>(i, j) = cv::pointPolygonTest(contours[0], cv::Point2f(j, i), true);
}
}
double minVal; double maxVal;
cv::minMaxLoc(raw_dist, &minVal, &maxVal, 0, 0, cv::Mat());
minVal = std::abs(minVal);
maxVal = std::abs(maxVal);
// depicting the distances graphically
cv::Mat mask = cv::Mat::zeros(inputImage.size(), CV_8UC1);
for (int i = 0; i < mask.rows; i++)
{
for (int j = 0; j < mask.cols; j++)
{
if (raw_dist.at<float>(i, j) < 0)
{
mask.at<uchar>(i, j) = static_cast<uchar>(0);
continue;
}
mask.at<uchar>(i, j) = static_cast<uchar>(255);
}
}
// inverse the input image
cv::Mat invInput;
cv::bitwise_not(inputImage, invInput);
// then get only the region of your triangle
cv::Mat outputImage;
invInput.copyTo(outputImage, mask);
cv::bitwise_not(outputImage, outputImage);
// display for debugging purpose
cv::imshow("inputImage", inputImage);
cv::imshow("lineMask", lineMask);
cv::imshow("mask", mask);
cv::imshow("outputImage", outputImage);
cv::waitKey();
This is your inputImage:
This is your lineMask:
This is your created binary mask:
And this is your final outputImage:
References:
OpenCV draw line
OpenCV findContours
Point Polygon Test
you can do it by using mask as shown with the code below
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main( int, char** argv )
{
Mat src = imread( argv[1] );
Mat gray;
cvtColor(src, gray, COLOR_BGR2GRAY );
gray = gray < 127;
vector<vector<Point> > contours;
findContours(gray, contours,
RETR_EXTERNAL,
CHAIN_APPROX_SIMPLE);
for( size_t i = 0; i< contours.size(); i++ )
{
Rect rect = boundingRect(contours[i]);
Mat mask = gray(rect);
Mat srcROI = src(rect);
srcROI.setTo(Scalar(0,0,255),mask);
imshow("srcROI",srcROI);
waitKey();
}
imshow( "result", src );
waitKey(0);
return(0);
}
EDIT: according the change on the question i suggest the test code below
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;
int main( int, char** argv )
{
Mat src = imread("lena.jpg");
vector<Point> points;
points.push_back( Point(200,200));
points.push_back( Point(370,370));
points.push_back( Point(220,410));
Mat mask = Mat::zeros( src.size(), CV_8UC1 );
fillConvexPoly( mask, points, Scalar( 255 ));
Rect rect = boundingRect( points );
Mat roi = src( rect ).clone();
mask = mask( rect ).clone();
rect.x = rect.x - 180;
rect.y = rect.y - 180;
Mat srcROI = src( rect );
roi.copyTo( srcROI, mask );
imshow( "result", src );
waitKey(0);
return(0);
}
As you told that you know co-ordinates of the triangle, using below code you can find triangle.
Mat image = imread("imagePath");
bitwise_not(image, image);
Mat grayImage;
cv::cvtColor(image, grayImage, CV_RGB2GRAY);
cv::vector<cv::vector<cv::Point> > contours;
cv::vector<cv::Vec4i> hierarchy;
cv::findContours(grayImage, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0));
Mat contourMat(grayImage.size(), grayImage.type(), Scalar(255));
for(int i = 0; i < contours.size(); i++)
{
if(contours[i].data()->x == 314 && contours[i].data()->y == 37)
drawContours(contourMat, contours, i, Scalar(0), CV_FILLED, 8, hierarchy);
}
imshow("WindowName", contourMat);
Hope this will help.

OpenCV, equalize histogram of image contour

I know that it is possible to equalize the histogram of an image like:
equalizeHist(image, image);
and if I want I can define a roi and equalize just this roi in the image:
Mat aux3 = image.clone();
equalizeHist(image(Rect(0,100, 200,200)), aux3(Rect(0,100, 200,200)));
What I would like to do now (and I don't know if it is possible), is to define a Roi(contour) using a vector of points (cv::vector contour) and equalize this roi (this roi not always will be a rectangle)
So, The question here is:
Is it possible to equalize a portion of the image that is not a rectangle using openCV functions?
There is no builtin function in OpenCV to perform histogram equalization with a mask. Still you can write your custom one.
Get a grayscale image:
// Load image
Mat3b img = imread("path_to_image");
// Convert to grayscale
Mat1b gray;
cvtColor(img, gray, COLOR_BGR2GRAY);
Form a mask from your points:
// Your vector of points
vector<Point> pts = { Point(300, 180), Point(450, 150), Point(600, 200), Point(650, 350), Point(300,300) };
// Create the mask
Mat1b mask(img.rows, img.cols, uchar(0));
vector<vector<Point>> ptsarray{pts};
fillPoly(mask, ptsarray, Scalar(255));
Call your custom function equalizeHistWithMask that equalize the image with a mask:
// Equalize with mask
Mat1b equalized;
equalizeHistWithMask(gray, equalized, mask);
Here the full code for reference, with the equalizeHistWithMask function:
#include <iostream>
#include <vector>
#include <algorithm>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
void equalizeHistWithMask(const Mat1b& src, Mat1b& dst, Mat1b mask = Mat1b())
{
int cnz = countNonZero(mask);
if (mask.empty() || ( cnz == src.rows*src.cols))
{
equalizeHist(src, dst);
return;
}
dst = src.clone();
// Histogram
vector<int> hist(256,0);
for (int r = 0; r < src.rows; ++r) {
for (int c = 0; c < src.cols; ++c) {
if (mask(r, c)) {
hist[src(r, c)]++;
}
}
}
// Cumulative histogram
float scale = 255.f / float(cnz);
vector<uchar> lut(256);
int sum = 0;
for (int i = 0; i < hist.size(); ++i) {
sum += hist[i];
lut[i] = saturate_cast<uchar>(sum * scale);
}
// Apply equalization
for (int r = 0; r < src.rows; ++r) {
for (int c = 0; c < src.cols; ++c) {
if (mask(r, c)) {
dst(r, c) = lut[src(r,c)];
}
}
}
}
int main()
{
// Load image
Mat3b img = imread("path_to_image");
// Convert to grayscale
Mat1b gray;
cvtColor(img, gray, COLOR_BGR2GRAY);
// Your vector of points
vector<Point> pts = { Point(300, 180), Point(450, 150), Point(600, 200), Point(650, 350), Point(300,300) };
// Create the mask
Mat1b mask(img.rows, img.cols, uchar(0));
vector<vector<Point>> ptsarray{pts};
fillPoly(mask, ptsarray, Scalar(255));
// Equalize with mask
Mat1b equalized;
equalizeHistWithMask(gray, equalized, mask);
imshow("Gray", gray);
imshow("Mask", mask);
imshow("Equalized", equalized);
waitKey();
return 0;
}
Credits
The code is based on this question on answers.opencv.org