how are convexity defects used with SVM classifier opencv c++? - c++

I want to use convexity defects of a human hand as input to a classifier. I want to do this to detect hand gestures (sign language alphabet). Can someone please help me.
The code below is available on the opencv documentation. I want to know how to use this for my the purpose stated above.
// Data for visual representation
int width = 512, height = 512;
Mat image = Mat::zeros(height, width, CV_8UC3);
// Set up training data
float labels[4] = { 1.0, -1.0, -1.0, -1.0 };
Mat labelsMat(4, 1, CV_32FC1, labels);
// Storing as Mat objects of floats
float trainingData[4][2] = { { 501, 10 }, { 255, 10 }, { 501, 255 }, { 10, 501 } };
Mat trainingDataMat(4, 2, CV_32FC1, trainingData);
// Set up SVM's parameters
CvSVMParams params;
params.svm_type = CvSVM::C_SVC;
params.kernel_type = CvSVM::LINEAR;
params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);
// Train the SVM
CvSVM SVM;
SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params);
Vec3b green(0, 255, 0), blue(255, 0, 0);
// Show the decision regions given by the SVM
for (int i = 0; i < image.rows; ++i)
for (int j = 0; j < image.cols; ++j)
{
Mat sampleMat = (Mat_<float>(1, 2) << j, i);
float response = SVM.predict(sampleMat);
if (response == 1)
image.at<Vec3b>(i, j) = green;
else if (response == -1)
image.at<Vec3b>(i, j) = blue;
}
// Show the training data
int thickness = -1;
int lineType = 8;
circle(image, Point(501, 10), 5, Scalar(0, 0, 0), thickness, lineType);
circle(image, Point(255, 10), 5, Scalar(255, 255, 255), thickness, lineType);
circle(image, Point(501, 255), 5, Scalar(255, 255, 255), thickness, lineType);
circle(image, Point(10, 501), 5, Scalar(255, 255, 255), thickness, lineType);
// Show support vectors
thickness = 2;
lineType = 8;
int c = SVM.get_support_vector_count();
for (int i = 0; i < c; ++i)
{
const float* v = SVM.get_support_vector(i);
circle(image, Point((int)v[0], (int)v[1]), 6, Scalar(128, 128, 128), thickness, lineType);
}
imwrite("result.png", image); // save the image
imshow("SVM Simple Example", image); // show it to the user
waitKey(0);
}

Related

Why do I get bad results with calcBackProject in opencv?

I create a project to reduce noise in the target image. I want to do something on Histograms, so I use calcHist to get the histogram of the image. When I use calcBackProject to recover images, the results are very different from the source image that I can't understand. The results show that the histogram of the two images is significant differences. Are there some problems with histogram processing?
By the way, my OpenCV version is 4.5.0.
int main()
{
Mat src = imread("./newpaperback.jpg");
imshow("src", src);
Mat gray;
cvtColor(src, gray, COLOR_BGR2GRAY);
imshow("gray", gray);
const int channels[] = {0};
Mat hist;
int dims = 1;
const int histSize[] = {256};;
float granges[] = {0, 256};
const float* ranges[] = { granges };
calcHist(&gray, 1, channels, Mat(), hist, dims, histSize, ranges, true, false);
int hist_height = 256;
Mat hist_image = Mat::zeros(hist_height, hist_height * 2, CV_8UC3);
double max_val;
minMaxLoc(hist, 0, &max_val, 0, 0);
for(int i = 0; i < hist_height; i++)
{
float bin_val = hist.at<float>(i);
segment[i] = bin_val * hist_height / max_val;
int intensity = bin_val * hist_height / max_val;
rectangle(hist_image, Point(i * 2, hist_height - 1), Point((i + 1) * 2 - 1, hist_height - intensity), Scalar(255, 255, 255));
}
imshow("hist", hist_image);
Mat back_img;
calcBackProject(&gray, 1, channels, hist, back_img, ranges, 1, true);
imshow("back", back_img);
waitKey(0);
return 0;
}

Is there a way to detect if a circle is connected to another circle with a line in opencv?

I'm trying to write a Maya plugin that recreates a 2d drawing of bones in UV space to 3D space. I'm starting with a simple plane with this image:
What I need is two find the circles and create a hierarchy.
I tried Nuzhny approach but I'm getting horizontal lines like:
My code:
Mat image;
image = imread("c:/pjs/sk.jpg"); // Read the file
cv::Mat hsv_image;
cv::cvtColor(image, hsv_image, cv::COLOR_BGR2HSV);
cv::Mat lower_red_hue_range;
cv::Mat upper_red_hue_range;
cv::Mat white_hue_range;
//Separate the lines and circles
cv::inRange(hsv_image, cv::Scalar(0, 100, 100), cv::Scalar(10, 255, 255), lower_red_hue_range);
cv::inRange(hsv_image, cv::Scalar(160, 100, 100), cv::Scalar(179, 255, 255), upper_red_hue_range);
cv::inRange(hsv_image, cv::Scalar(0, 0, 20), cv::Scalar(0, 0, 255), white_hue_range);
cv::Mat red_hue_image;
cv::addWeighted(lower_red_hue_range, 1.0, upper_red_hue_range, 1.0, 0.0, red_hue_image);
cv::GaussianBlur(red_hue_image, red_hue_image, cv::Size(9, 9), 2, 2);
//Identify circles
std::vector<cv::Vec3f> circles;
cv::HoughCircles(red_hue_image, circles, HOUGH_GRADIENT, 1, red_hue_image.rows / 8, 100, 20, 0, 0);
if (circles.size() == 0) std::exit(-1);
for (size_t current_circle = 0; current_circle < circles.size(); ++current_circle) {
cv::Point center(std::round(circles[current_circle][0]), std::round(circles[current_circle][1]));
int radius = std::round(circles[current_circle][2]);
cv::circle(image, center, radius, cv::Scalar(0, 255, 0), 5);
}
//Get the contours
cv::threshold(white_hue_range, white_hue_range, 11, 255, cv::THRESH_BINARY);
cv::Mat element = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(3, 3));
element = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(20, 20));
cv::dilate(white_hue_range, white_hue_range, element);
cv::dilate(white_hue_range, white_hue_range, element);
cv::erode(white_hue_range, white_hue_range, element);
cv::erode(white_hue_range, white_hue_range, element);
element = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(5, 5));
cv::dilate(white_hue_range, white_hue_range, element);
Mat gray;
gray = white_hue_range;
Canny(gray, gray, 40, 100, 7);
/// Find contours
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
RNG rng(12345);
findContours(gray, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
/// Draw contours
Mat drawing = Mat::zeros(gray.size(), CV_8UC3);
for (int i = 0; i < contours.size(); i++)
{
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());
}
//Get the lines
vector<vector<Point2f> > lines;
vector<Point> approx;
for (unsigned int i = 0; i < contours.size(); i++)
{
if (contours[i].size() > 4) {
//cv::Rect box = cv::fitEllipse(contours[i]);
cv::RotatedRect box = cv::fitEllipseAMS(contours[i]);
cv::Point2f pts[4];
box.points(pts);
vector<cv::Point2f> line_pts;
line_pts.resize(2);
line_pts[0] = (pts[0] + pts[1]) / 2;
line_pts[1] = (pts[2] + pts[3]) / 2;
lines.push_back(line_pts);
}
}
for (int i = 0; i < lines.size(); i++)
{
line(image, lines[i].at(0), lines[i].at(1), 128, 4, LINE_8, 0);
}
imshow("Result window", image);
cvtColor to HSV.
inRange(redFrom, redTo) + findContours to find red circles.
inRange(whiteFrom, whiteTo) + findContours to find white lines.
Line contour to line:
cv::RotatedRect box = cv::fitEllipse(line_contours[i]);
cv::Point2f pts[4];
box.points(pts);
cv::Point2f line_pts[2];
line_pts[0] = (pts[0] + pts[3]) / 2;
line_pts[1] = (pts[1] + pts[2]) / 2;
Nested loops to find a nearest circle for each line point.

How to find rectangle in black region opencv (C++)

I'm newbie OpenCV. I am using opencv for find position attach a stamp in image. The stamp can't overlap with other object in image.
Example binary image with white region is object on image, black region is none object
Example image
Result : Find rect in black region (in white circle) can attach stamp
Result imagge
Please help me find rect in black region same blue rect.
Thank you!
If you know about rectangles count then it can use kmeans for clusterization points.
First get only blue points and binarization they:
cv::Mat img = cv::imread("NQdmi.png", cv::IMREAD_COLOR);
std::vector<cv::Mat> chans;
cv::split(img, chans);
cv::Mat diff;
cv::absdiff(chans[2], chans[1], diff);
cv::threshold(diff, diff, 1, 255, cv::THRESH_BINARY);
cv::imshow("diff", diff);
Only blue points:
Clusterization points and find rotated rectangles:
std::vector<cv::Point2f> points;
for (int y = 0; y < diff.rows; ++y)
{
for (int x = 0; x < diff.cols; ++x)
{
if (diff.at<uchar>(y, x))
{
points.emplace_back(x, y);
}
}
}
cv::Mat pointsKmeans(points.size(), 1, CV_32FC2, &points[0]);
cv::Mat labels;
int clusterCount = 2;
cv::Mat centers;
cv::kmeans(pointsKmeans, clusterCount, labels,
cv::TermCriteria(cv::TermCriteria::EPS+cv::TermCriteria::COUNT, 100, 1.0),
3, cv::KMEANS_PP_CENTERS, centers);
std::vector<cv::Point2f> points1;
std::vector<cv::Point2f> points2;
cv::Mat draw = img.clone();
for (size_t i = 0; i < points.size(); ++i)
{
int clusterIdx = labels.at<int>(i);
if (clusterIdx > 0)
{
cv::circle(draw, points[i], 2, cv::Scalar(255, 0, 0), cv::FILLED, cv::LINE_AA);
points1.push_back(points[i]);
}
else
{
cv::circle(draw, points[i], 2, cv::Scalar(0, 0, 255), cv::FILLED, cv::LINE_AA);
points2.push_back(points[i]);
}
}
auto DrawRRect = [draw](const std::vector<cv::Point2f>& pp)
{
cv::RotatedRect rr = cv::minAreaRect(pp);
cv::Point2f corners[4];
rr.points(corners);
cv::line(draw, corners[0], corners[1], cv::Scalar(0, 255, 0), 2);
cv::line(draw, corners[1], corners[2], cv::Scalar(0, 255, 0), 2);
cv::line(draw, corners[2], corners[3], cv::Scalar(0, 255, 0), 2);
cv::line(draw, corners[3], corners[0], cv::Scalar(0, 255, 0), 2);
};
DrawRRect(points1);
DrawRRect(points2);
cv::imshow("draw", draw);
Result:

Number plate localization in bulk of images

I have got bulk of car images and want to perform automatic number plate recognition but i am stuck at localization phase .I want to get license plate individually as output on which i can perform recognition.Here is my code for localization:
int main(int args,char* argv)
{
//String filename;
//filename="";
cv::Mat image=cv::imread("C:\\Users\\Sarora\\Downloads\\Images\\frame_1375.jpg",CV_LOAD_IMAGE_COLOR);
cv::Mat img;
cv::Mat img_sobel;
cv::Mat grad_x, grad_y;
cv::Mat abs_grad_x, abs_grad_y;
cv::Mat imgContours;
//vector <Plate>result;
cv::cvtColor(image, img, CV_BGR2GRAY);
blur(img, img, cv::Size(5,5));
//cv::namedWindow("Img1.jpg", CV_WINDOW_AUTOSIZE );
//sobel filter applied on image..............................................................................................
cv::Sobel(img, grad_x, CV_16S, 1, 0,3,1,0, cv::BORDER_DEFAULT);
convertScaleAbs( grad_x, abs_grad_x );
cv::Sobel(img, grad_y, CV_16S, 0, 1,3,1,0, cv::BORDER_DEFAULT);
convertScaleAbs( grad_y, abs_grad_y );
addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, img_sobel );
cv::imwrite("Img2.jpg",img_sobel);
//Threshold the image...................................................................................................................
cv::Mat Thresh_img;
threshold(img_sobel, Thresh_img, 0, 255, CV_THRESH_OTSU+CV_THRESH_BINARY);
//imshow("Threshold", Thresh_img);
//Morphological close operation applied................................................................................................
cv::Mat element1=cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
cv::morphologyEx(Thresh_img,Thresh_img,CV_MOP_CLOSE,element1);
cv::imwrite("Close1.jpg",Thresh_img);
//cv::waitKey(5000);
//find Contours of whole image......................................................................................................
std::vector <std::vector<cv::Point>> contours;
cv::findContours(Thresh_img, contours,CV_RETR_LIST,CV_CHAIN_APPROX_NONE);
//cv::drawContours(image,contours,-1,cv::Scalar(0,0,255),3);
cv::imwrite("Contours1.jpg",image);
std::vector <std::vector<cv::Point>>::iterator itc= contours.begin();
std::vector <cv::RotatedRect> rects;
//vector<vector<Point> > contours_poly(rects.size());
//vector<Rect> boundRect(rects.size());
//Remove patch not inside the limits of aspect ratio and area..................................................................................
while (itc!=contours.end()) {
cv::RotatedRect mr= cv::minAreaRect(cv::Mat(*itc));
if( !verifySizes(mr))
{ itc= contours.erase(itc);
}else {
++itc;
rects.push_back(mr);
}
}
cv::Mat drawing;
vector<vector<cv::Point> > contours_poly(rects.size());
vector<cv::Rect> boundRect(rects.size());
//Draw contours
cv::Mat output;
image.copyTo(output);
for(int i=0;i<rects.size();i++)
{
approxPolyDP(cv::Mat(contours[i]), contours_poly[i], 10, true);
boundRect[i] = cv::boundingRect(cv::Mat(contours_poly[i]));
}
//cv::imwrite("Contours.jpg", output);
for (int i = 0; i < rects.size(); i++)
{
drawContours(output, contours_poly, i, CV_RGB(255, 255, 255), 1, 8, vector<cv::Vec4i>(), 0, cv::Point());
//rectangle(output, boundRect[i].tl(), boundRect[i].br(), CV_RGB(0, 255, 0), 3, 8, 0);
}
cv::imwrite("drawing1.jpg",output);
}
bool verifySizes(cv::RotatedRect mr){
float error=0.4;
//Set a min and max area. All other patches are discarded
int min= 5; // minimum area
int max=1000; // maximum area
//Get only patches that match
float rmin= 1;
float rmax= 10;
int area= mr.size.height * mr.size.width;
float r= (float)mr.size.width / (float)mr.size.height;
if(r<1)
r= (float)mr.size.height / (float)mr.size.width;
if(( area < min || area > max ) || ( r < rmin || r > rmax )){
return false;
}else{
return true;
}
}
I have performed sobel filter,Threshold(OTSU+binary),Morphological operation CLOSE,findContours(),removal of one not inside limits of area and aspect ratio and approxPolyDP on the imageThis is my input image
This is approxPolyDP image
Problem is output image is not forming rectangles around License plate.Can anyone tell what is wrong in the code and also how can i proceed further to automatically find license plates in bulk of images?I am confused.
Thank you

Getting the SVM example of OpenCV to run in Version 3.0.0 with c++ [duplicate]

I have just started my learning on SVM using C++ OpenCV and was referring to the SVM documentation here. I wanted to try out the sample source code from the link to get familiar with it first but I couldn't run the sample source code. It returns the error :
Error 1 error C2065: 'CvSVMParams' : undeclared identifier
I'm using Visual Studio 2012 with OpenCV 3.0.0. The setup process should be correct as all other codes are working well except this.
A lot of things changed from OpenCV 2.4 to OpenCV 3.0. Among others, the machine learning module, which isn't backward compatible.
This is the OpenCV tutorial code for the SVM, update for OpenCV 3.0:
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include "opencv2/imgcodecs.hpp"
#include <opencv2/highgui.hpp>
#include <opencv2/ml.hpp>
using namespace cv;
using namespace cv::ml;
int main(int, char**)
{
// Data for visual representation
int width = 512, height = 512;
Mat image = Mat::zeros(height, width, CV_8UC3);
// Set up training data
int labels[4] = { 1, -1, -1, -1 };
Mat labelsMat(4, 1, CV_32SC1, labels);
float trainingData[4][2] = { { 501, 10 }, { 255, 10 }, { 501, 255 }, { 10, 501 } };
Mat trainingDataMat(4, 2, CV_32FC1, trainingData);
// Set up SVM's parameters
Ptr<SVM> svm = SVM::create();
svm->setType(SVM::C_SVC);
svm->setKernel(SVM::LINEAR);
svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));
// Train the SVM with given parameters
Ptr<TrainData> td = TrainData::create(trainingDataMat, ROW_SAMPLE, labelsMat);
svm->train(td);
// Or train the SVM with optimal parameters
//svm->trainAuto(td);
Vec3b green(0, 255, 0), blue(255, 0, 0);
// Show the decision regions given by the SVM
for (int i = 0; i < image.rows; ++i)
for (int j = 0; j < image.cols; ++j)
{
Mat sampleMat = (Mat_<float>(1, 2) << j, i);
float response = svm->predict(sampleMat);
if (response == 1)
image.at<Vec3b>(i, j) = green;
else if (response == -1)
image.at<Vec3b>(i, j) = blue;
}
// Show the training data
int thickness = -1;
int lineType = 8;
circle(image, Point(501, 10), 5, Scalar(0, 0, 0), thickness, lineType);
circle(image, Point(255, 10), 5, Scalar(255, 255, 255), thickness, lineType);
circle(image, Point(501, 255), 5, Scalar(255, 255, 255), thickness, lineType);
circle(image, Point(10, 501), 5, Scalar(255, 255, 255), thickness, lineType);
// Show support vectors
thickness = 2;
lineType = 8;
Mat sv = svm->getSupportVectors();
for (int i = 0; i < sv.rows; ++i)
{
const float* v = sv.ptr<float>(i);
circle(image, Point((int)v[0], (int)v[1]), 6, Scalar(128, 128, 128), thickness, lineType);
}
imwrite("result.png", image); // save the image
imshow("SVM Simple Example", image); // show it to the user
waitKey(0);
}
The output should look like:
I found the code above worked but I needed to make a small modification to convert the labels to integers. The modification is in bold:
// Set up training data **Original**:
int labels[4] = { 1, -1, -1, -1 };
Mat labelsMat(4, 1, **CV_32SC1**, labels);
// Set up training data **Modified**:
int labels[4] = { 1, -1, -1, -1 };
Mat labelsMat(4, 1, **CV_32S**, labels);