I have already reffered to the following links:
Link 1 and Link 2
From the above i have to managed to write the following :
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/ml/ml.hpp>
using namespace cv;
using namespace std;
int main(){
int num_files = 2;
int width = 128, height = 128;
Mat image[2];
image[0] = imread("Tomato.jpg");
image[1] = imread("Melon.jpg");
Mat new_image(2,height*width,CV_32FC1); //Training sample from input images
int ii = 0;
for (int i = 0; i < num_files; i++){
Mat temp = image[i];
ii = 0;
for (int j = 0; j < temp.rows; j++){
for (int k = 0; k < temp.cols; k++){
new_image.at<float>(i, ii++) = temp.at<uchar>(j, k);
}
}
}
//new_image.push_back(image[0].reshape(0, 1));
//new_image.push_back(image[1].reshape(0, 1));
Mat labels(num_files, 1, CV_32FC1);
labels.at<float>(0, 0) = 1.0;//tomato
labels.at<float>(1, 0) = -1.0;//melon
imshow("New image", new_image);
printf("%f %f", labels.at<float>(0, 0), labels.at<float>(1, 0));
CvSVMParams params;
params.svm_type = CvSVM::C_SVC;
params.kernel_type = CvSVM::LINEAR;
params.gamma = 3;
params.degree = 3;
params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);
CvSVM svm;
svm.train(new_image, labels, Mat(), Mat(), params);
svm.save("svm.xml"); // saving
svm.load("svm.xml"); // loading
Mat test_img = imread("Tomato.jpg");
test_img=test_img.reshape(0, 1);
imshow("shit_image", test_img);
test_img.convertTo(test_img, CV_32FC1);
svm.predict(test_img);
waitKey(0);
}
I get the following error:
unsupported format or combination of formats, input sample must have 32FC1 type in cvPreparePredictData ...
I followed all steps in the second link. All matrices are 32FC1 type.
What am I missing?
Is there something wrong with the svm parameters ?
The error is caused when i try to predict a result.
check 1) Tomato.jpg and Melon.jpg size is 128*128 ?
2) both images are grayscale?
if not. try this code: I just add resize(), cvtColor() and print result
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/ml/ml.hpp>
#include <opencv2\imgproc\imgproc.hpp>
using namespace cv;
using namespace std;
int main(){
int num_files = 2;
int width = 128, height = 128;
Mat image[2];
image[0] = imread("Tomato.jpg", 0);
image[1] = imread("Melon.jpg", 0);
resize(image[0], image[0], Size(width, height));
resize(image[1], image[1], Size(width, height));
Mat new_image(2, height*width, CV_32FC1); //Training sample from input images
int ii = 0;
for (int i = 0; i < num_files; i++){
Mat temp = image[i];
ii = 0;
for (int j = 0; j < temp.rows; j++){
for (int k = 0; k < temp.cols; k++){
new_image.at<float>(i, ii++) = temp.at<uchar>(j, k);
}
}
}
//new_image.push_back(image[0].reshape(0, 1));
//new_image.push_back(image[1].reshape(0, 1));
Mat labels(num_files, 1, CV_32FC1);
labels.at<float>(0, 0) = 1.0;//tomato
labels.at<float>(1, 0) = -1.0;//melon
imshow("New image", new_image);
printf("%f %f", labels.at<float>(0, 0), labels.at<float>(1, 0));
CvSVMParams params;
params.svm_type = CvSVM::C_SVC;
params.kernel_type = CvSVM::LINEAR;
params.gamma = 3;
params.degree = 3;
params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);
CvSVM svm;
svm.train(new_image, labels, Mat(), Mat(), params);
svm.save("svm.xml"); // saving
svm.load("svm.xml"); // loading
Mat test_img = imread("Tomato.jpg", 0);
resize(test_img, test_img, Size(width, height));
test_img = test_img.reshape(0, 1);
imshow("shit_image", test_img);
test_img.convertTo(test_img, CV_32FC1);
float res = svm.predict(test_img);
if (res > 0)
cout << endl << "Tomato";
else
cout << endl << "Melon";
waitKey(0);
}
Related
Here are my full code, i am trying to use opencv 4.5.5 for feature detection and relative pose calculation.
I tried using vector<vector> as first and second input type, but it didnot work.
I think this error is something related to input parameter type, but i donot know how to fix it, huge thanks for any help!
Detection and Descriptor calculation works fine.
#include <iostream>
#include <opencv2/features2d.hpp>
#include <opencv2/sfm/fundamental.hpp>
#include <opencv2/highgui.hpp>
#include <vector>
#include <chrono>
using std::vector;
static cv::Ptr<cv::ORB> mOrbTracker = nullptr;
static cv::Ptr<cv::DescriptorMatcher> mMatcher = nullptr;
void init(const unsigned int &nFeatures, const float &scaleFactor,
const unsigned int &nPyramid, const unsigned int &edgeThreshold,
const int &sourceImgToPyramidLevel, const int &wta_k,
const cv::ORB::ScoreType &sType, const unsigned int &fastThreshold,
const cv::DescriptorMatcher::MatcherType &matcherType) {
mOrbTracker = cv::ORB::create(nFeatures, scaleFactor, nPyramid,
edgeThreshold, sourceImgToPyramidLevel, wta_k,
sType, edgeThreshold, fastThreshold);
mMatcher = cv::DescriptorMatcher::create(matcherType);
}
int main() {
cv::Mat img1, img2;
img1 = cv::imread("/home/wgf/docs/1.jpg", cv::IMREAD_COLOR);
img2 = cv::imread("/home/wgf/docs/2.jpg", cv::IMREAD_COLOR);
init(600, 1.2f, 8, 31, 0, 2,
cv::ORB::HARRIS_SCORE, 20, cv::DescriptorMatcher::BRUTEFORCE_HAMMING);
cv::Mat firstDescriptors = cv::Mat();
cv::Mat secondDescriptors = cv::Mat();
vector<cv::KeyPoint> mTempFirst, mTempSecond;
vector<cv::DMatch> mTempMatches, mTempGoodMatches;
std::chrono::time_point<std::chrono::system_clock> start = std::chrono::system_clock::now();
detectAndComputeDescriptors(img1, mTempFirst, firstDescriptors);
detectAndComputeDescriptors(img2, mTempSecond, secondDescriptors);
auto dur_feature_extraction = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now() - start);
mMatcher->match(firstDescriptors, secondDescriptors, mTempMatches);
float maxDist = std::numeric_limits<float>::min();
for (int i = 0; i < mTempMatches.size(); ++i) {
maxDist = std::max(maxDist, mTempMatches[i].distance);
}
float mMatchesDistanceThreshold = 0.6f;
for (int j = 0; j < mTempMatches.size(); ++j) {
if (mTempMatches[j].distance < mMatchesDistanceThreshold * maxDist) {
mTempGoodMatches.emplace_back(mTempMatches[j]);
}
}
cv::Mat firstKeyPoints = cv::Mat(2, mTempGoodMatches.size(), CV_32F);
cv::Mat secondKeyPoints = cv::Mat(2, mTempGoodMatches.size(), CV_32F);
for (int k = 0; k < mTempGoodMatches.size(); k++) {
firstKeyPoints.at<float>(0, k) = mTempFirst[mTempGoodMatches[k].queryIdx].pt.x;
firstKeyPoints.at<float>(1, k) = mTempFirst[mTempGoodMatches[k].queryIdx].pt.y;
secondKeyPoints.at<float>(0, k) = mTempSecond[mTempGoodMatches[k].trainIdx].pt.x;
secondKeyPoints.at<float>(1, k) = mTempSecond[mTempGoodMatches[k].trainIdx].pt.y;
}
cv::Mat R = cv::Mat(3, 3, CV_32F);
cv::Mat t = cv::Mat(3, 1, CV_32F);
float scale = 0.0f;
cv::Mat currentPose;
cv::sfm::computeOrientation(firstKeyPoints, secondKeyPoints, R, t, scale);
currentPose = cv::Mat::eye(4, 4, CV_32F);
currentPose.at<float>(0, 0) = R.at<float>(0, 0);
currentPose.at<float>(0, 1) = R.at<float>(0, 1);
currentPose.at<float>(0, 2) = R.at<float>(0, 2);
currentPose.at<float>(1, 0) = R.at<float>(1, 0);
currentPose.at<float>(1, 1) = R.at<float>(1, 1);
currentPose.at<float>(1, 2) = R.at<float>(1, 2);
currentPose.at<float>(2, 0) = R.at<float>(2, 0);
currentPose.at<float>(2, 1) = R.at<float>(2, 1);
currentPose.at<float>(2, 2) = R.at<float>(2, 2);
currentPose.at<float>(0, 3) = t.at<float>(0, 0);
currentPose.at<float>(1, 3) = t.at<float>(1, 0);
currentPose.at<float>(2, 3) = t.at<float>(2, 0);
cv::Mat re;
cv::drawMatches(img1, mTempFirst, img2, mTempSecond, mTempGoodMatches, re);
cv::imshow("match", re);
cv::waitKey();
return 0;
}
My code shows me values that are not accurate and i am not sure what else to try. My goal is to get the values of y such as rows, so that I can read the image and put it in an array. Ive looked at examples and Stack Overflow is literally my last option.
#include<iostream>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat Rgb;
Mat Grey;
Mat image;
//Mat Histogram;
Rgb = imread("license.jpg", WINDOW_AUTOSIZE);
cvtColor(Rgb, Grey, cv::COLOR_BGR2GRAY);
threshold(Grey, image, 150, 250, THRESH_BINARY);
int histogram[255];
for (int i = 0; i < 255; i++)
{
histogram[i] = 0;
}
for (int y = 0; y < image.rows; y++)
//for (int x = 0; x < image.cols; x++)
histogram[(int)image.at<uchar>(y)]++;
//histogram[(int)image.at<uchar>(y, x)]++;
for (int i = 0; i < 255; i++)
cout << histogram[i] << " ";
// draw the histograms
int hist_w = 512; int hist_h = 400;
int bin_w = cvRound((double)hist_w / 255);
Mat histImage(hist_h, hist_w, CV_8UC1, Scalar(255, 255, 255));
int max = histogram[0];
for (int i = 1; i < 256; i++) {
if (max < histogram[i]) {
max = histogram[i];
}
}
for (int i = 0; i < 255; i++) {
histogram[i] = ((double)histogram[i] / max)*histImage.rows;
}
for (int i = 0; i < 255; i++)
{
line(histImage, Point(bin_w*(i), hist_h),
Point(bin_w*(i), hist_h - histogram[i]),
Scalar(0, 0, 0), 1, 8, 0);
}
imshow("Image", image);
waitKey(0);
cv::destroyAllWindows();
return 0;
}
Results have numbers like 319 and other values and I am only looking to get 0 or 255
I'm writing a program to recognize the numbers on the image.
I do not see an error in the code. You receive a runtime exception. Indicates Mat.
I use Visual Studio 2015 Community and OpenCV 3.1.
Kmeans segmentation code found on stackoverflow.
Exeption:
test_opencv_nuget.exe!cv::Mat::at >(int i0, int i1)Строка 918 C++
mat.inl.hpp file
line:
CV_DbgAssert((unsigned)(i1 * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels()));
#include "opencv2/opencv.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/core.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
VideoCapture cap;
if (!cap.open(0))
return 0;
Mat camera_image;
Mat gray_scale_image;
Mat binary_image;
Mat otsu_binary_image;
Mat laplas_circuit_image;
for (;;)
{
cap >> camera_image;
cvtColor(camera_image, gray_scale_image, cv::COLOR_RGB2GRAY);
threshold(gray_scale_image, otsu_binary_image, 0, 255, CV_THRESH_OTSU);
Mat laplas_kernel = (Mat_<float>(3, 3) << 0, 1, 0,
1, -4, 1,
0, 1, 0);
filter2D(otsu_binary_image, laplas_circuit_image, -1, laplas_kernel);
Mat samples(otsu_binary_image.rows * otsu_binary_image.cols, 3, CV_32F);
for (int y = 0; y < otsu_binary_image.rows; y++)
for (int x = 0; x < otsu_binary_image.cols; x++)
for (int z = 0; z < 3; z++)
samples.at<float>(y + x*otsu_binary_image.rows, z) = otsu_binary_image.at<Vec3b>(y, x)[z];
int clusterCount = 5;
Mat labels;
int attempts = 5;
Mat centers;
kmeans(samples, clusterCount, labels, TermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 10000, 0.0001), attempts, KMEANS_PP_CENTERS, centers);
Mat kmeans_image(otsu_binary_image.size(), otsu_binary_image.type());
for (int y = 0; y < otsu_binary_image.rows; y++)
for (int x = 0; x < otsu_binary_image.cols; x++)
{
int cluster_idx = labels.at<int>(y + x*otsu_binary_image.rows, 0);
kmeans_image.at<Vec3b>(y, x)[0] = centers.at<float>(cluster_idx, 0);
kmeans_image.at<Vec3b>(y, x)[1] = centers.at<float>(cluster_idx, 1);
kmeans_image.at<Vec3b>(y, x)[2] = centers.at<float>(cluster_idx, 2);
}
imshow("original", camera_image);
imshow("gray_scale", gray_scale_image);
imshow("otsu", otsu_binary_image);
imshow("laplas_circuit", laplas_circuit_image);
imshow("clusters", kmeans_image);
char c = cvWaitKey(33);
if (c == 27) break; // press ESC
}
return 0;
}
I am trying to make a classifier using OpenCV 3.0.0's CvSVM and color histogram. I already tried to make my own using the following code to make the datasets:
int labels[510];
if (label.compare("raw")){
for (int i = 0; i < 509; i++){
labels[i] = 1;
}
}
else if (label.compare("ripe")){
for (int i = 0; i < 509; i++){
labels[i] = 2;
}
}
else if (label.compare("rotten")){
for (int i = 0; i < 509; i++){
labels[i] = 3;
}
}
float trainingData[510][2];
for (int i = 0; i < 254; i++){
trainingData[i][1] = r_hist.at<float>(i - 1);
trainingData[i][2] = i;
}
int j = 0;
for (int i = 255; i < 509; i++){
trainingData[i][1] = g_hist.at<float>(j - 1);
trainingData[i][2] = i;
j++;
}
And this code for the SVM:
int width = 512, height = 512;
Mat image = Mat::zeros(height, width, CV_8UC3);
Mat labelsMat(510, 1, CV_32SC1, labels);
Mat trainingDataMat(510, 2, CV_32FC1, trainingData);
Ptr < cv::ml::SVM > svm = SVM::create();
svm = cv::Algorithm::load<ml::SVM>("svm.xml");
svm->setC(0.01);
svm->setType(ml::SVM::C_SVC);
svm->setKernel(ml::SVM::LINEAR);
svm->setTermCriteria((cvTermCriteria(TermCriteria::MAX_ITER, 100, 1e6)));
svm->train(trainingDataMat, ROW_SAMPLE, labelsMat);
svm->save("svm.xml");
The problem with the code above is that it won't save properly. Is there a better way to do it?
I'm having problems with the DFT function in OpenCV 2.4.8 for c++.
I used an image of a 10 phases sinus curve to compare the old cvDFT() with the newer c++ function DFT() (one dimensional DFT row-wise).
The old version gives me logical results: very high peak at pixel 0 and 10, the rest being almost 0.
The new version gives me strange results with peaks all over the spectrum.
Here is my code:
#include "stdafx.h"
#include <opencv2\core\core_c.h>
#include <opencv2\core\core.hpp>
#include <opencv2\imgproc\imgproc_c.h>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\highgui\highgui_c.h>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\legacy\compat.hpp>
using namespace cv;
void OldMakeDFT(Mat original, double* result)
{
const int width = original.cols;
const int height = 1;
IplImage* fftBlock = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
IplImage* imgReal = cvCreateImage(cvSize(width, height), IPL_DEPTH_32F, 1);
IplImage* imgImag = cvCreateImage(cvSize(width, height), IPL_DEPTH_32F, 1);
IplImage* imgDFT = cvCreateImage(cvSize(width, height), IPL_DEPTH_32F, 2);
Rect roi(0, 0, width, 1);
Mat image_roi = original(roi);
fftBlock->imageData = (char*)image_roi.data;
//cvSaveImage("C:/fftBlock1.png", fftBlock);
cvConvert(fftBlock, imgReal);
cvMerge(imgReal, imgImag, NULL, NULL, imgDFT);
cvDFT(imgDFT, imgDFT, (CV_DXT_FORWARD | CV_DXT_ROWS));
cvSplit(imgDFT, imgReal, imgImag, NULL, NULL);
double re,imag;
for (int i = 0; i < width; i++)
{
re = ((float*)imgReal->imageData)[i];
imag = ((float*)imgImag->imageData)[i];
result[i] = re * re + imag * imag;
}
cvReleaseImage(&imgReal);
cvReleaseImage(&imgImag);
cvReleaseImage(&imgDFT);
cvReleaseImage(&fftBlock);
}
void MakeDFT(Mat original, double* result)
{
const int width = original.cols;
const int height = 1;
Mat fftBlock(1,width, CV_8UC1);
Rect roi(0, 0, width, height);
Mat image_roi = original(roi);
image_roi.copyTo(fftBlock);
//imwrite("C:/fftBlock2.png", fftBlock);
Mat planes[] = {Mat_<float>(fftBlock), Mat::zeros(fftBlock.size(), CV_32F)};
Mat complexI;
merge(planes, 2, complexI);
dft(complexI, complexI, DFT_ROWS); //also tried with DFT_COMPLEX_OUTPUT | DFT_ROWS
split(complexI, planes);
double re, imag;
for (int i = 0; i < width; i++)
{
re = (float)planes[0].data[i];
imag = (float)planes[1].data[i];
result[i] = re * re + imag * imag;
}
}
bool SinusFFTTest()
{
const int size = 1024;
Mat sinTest(size,size,CV_8UC1, Scalar(0));
const int n_sin_curves = 10;
double deg_step = (double)n_sin_curves*360/size;
for (int j = 0; j < size; j++)
{
for (int i = 0; i <size; i++)
{
sinTest.data[j*size+i] = 127.5 * sin(i*deg_step*CV_PI/180) + 127.5;
}
}
double* result1 = new double[size];
double* result2 = new double[size];
OldMakeDFT(sinTest,result1);
MakeDFT(sinTest,result2);
bool identical = true;
for (int i = 0; i < size; i++)
{
if (abs(result1[i] - result2[i]) > 1000)
{
identical = false;
break;
}
}
delete[] result1;
delete[] result2;
return identical;
}
int _tmain(int argc, _TCHAR* argv[])
{
if (SinusFFTTest())
{
printf("identical");
}
else
{
printf("different");
}
getchar();
return 0;
}
Could someone explain the difference?
imgReal - is not filled with zeroes by default.
The bug in in the MakeDFT() function:
re = (float)planes[0].data[i];
imag = (float)planes[1].data[i];
data[i]'s type is uchar, and its conversion to float is not right.
The fix:
re = planes[0].at<float>(0,i);
imag = planes[1].at<float>(0,i);
After this change, the old and the new DFT versions gives the same results. Or, you can use cv::magnitude() instead of calculating the sum of squares of re and imag:
Mat magn;
magnitude(planes[0], planes[1], magn);
for (int i = 0; i < width; i++)
result[i] = pow(magn.at<float>(0,i),2);
This gives also the same result as the old cvDFT.