I have to find the ruler position from an image by using opencv.I am able to detect the color of the ruler(green). How can i read all the pixel from an image and get the upper and lower position of ruler.
void findrulerPosition(cv::Mat image, int indx) {
std::stringstream ss;//create a stringstream
ss << indx;//add number to the stream
cv::Mat hsv;
cvtColor(image, hsv, CV_BGR2HSV);
String filename = OUTPUT_FOLDER + "hsv" + ss.str() + ".png";
imwrite(filename, hsv );
cv::Mat hsvbw;
inRange(hsv, cv::Scalar(30,0,0), cv::Scalar(80, 255, 255), hsvbw);
//inRange(hsv, cv::Scalar(12,255,255), cv::Scalar(23, 245, 255), hsvbw);
//inRange(image, cv::Scalar(0,64,255), cv::Scalar(0, 207, 255), hsvbw);
filename = OUTPUT_FOLDER + "hsvbw" + ss.str() + ".png";
imwrite(filename, hsvbw );
vector<vector<Point> > contours;
findContours(hsvbw.clone(), contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
cv::Mat dst = Mat::zeros(image.size(), image.type());
drawContours(dst, contours, -1, Scalar::all(255), CV_FILLED);
this->cmpddst &= dst;
dst &= image;
this->cmpddst &= image;
filename = OUTPUT_FOLDER + "cmpddst" + ss.str() + ".png";
imwrite(filename, this->cmpddst );
filename = OUTPUT_FOLDER + "dst" + ss.str() + ".png";
imwrite(filename, dst );
}
Here's what I've done:
A bit improved your green range because yours is not detecting green color - it's detecting many other colors.
Find contours on image.
Find contour with area bigger than 100.
Find up and low points of contour.
Draw these 2 points.
Mat src = imread("input.png"), tmp;
cvtColor(src, tmp, CV_BGR2HSV_FULL);
inRange(tmp, Scalar(50, 50, 50), Scalar(70, 255, 255), tmp);
vector<vector<Point> > contours;
findContours(tmp, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
int upY = INT_MAX, lowY = 0, upX, lowX;
for (int i=0; i<contours.size(); i++)
{
if (contourArea(contours[i]) > 100)
{
for (int j=0; j<contours[i].size(); j++)
{
if (contours[i][j].y > lowY)
{
lowY = contours[i][j].y;
lowX = contours[i][j].x;
}
if (contours[i][j].y < upY)
{
upY = contours[i][j].y;
upX = contours[i][j].x;
}
}
cout << "low = (" << lowX << ", " << lowY << ")"<< endl
<< "up = (" << upX << ", " << upY << ")"<< endl;
break;
}
}
circle(src, Point(lowX, lowY), 3, Scalar(255, 0, 255));
circle(src, Point(upX, upY), 3, Scalar(255, 0, 255));
imshow("Window", src);
waitKey();
Here's result:
Related
I am a newbie to c++ and the IDE I am using is Visual Studio '22. I have written a code to detect a face (eyes and mouth too) and save the roi to a folder on the pc. Now what it does can be thought of as an auto-capture of the roi as soon as the face is detected.
I now want to create the function for "force capture", for which I will need to have a button and add pretty much the same code I wrote for auto-capture to give it functionality.
How do I add the button and make it perform its task?
I found related answers but they use Qt not sure how to apply that here.
Thanks a ton! Really need help.
#include <opencv2/opencv.hpp>
#include <opencv2/dnn/dnn.hpp>
//(1) include face header
#include "opencv2/face.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
//(2) include face header
#include "opencv2/objdetect.hpp"
#include <iostream>
#include <opencv2/imgproc/types_c.h>
//file handling
#include <fstream>
#include <sstream>
using namespace cv;
using namespace std;
using namespace ml;
using namespace cv::face;
//(3) Global variables
Ptr<Facemark> facemark; //mark detection
CascadeClassifier faceDetector, mouth, eye, eye1; //face detection
string name, filename;
void process(Mat img, Mat imgcol) {
vector<Rect> faces;
faceDetector.detectMultiScale(img, faces);
Mat imFace;
if (faces.size() != 0) {
for (size_t i = 0; i < faces.size(); i++)
{
cv::rectangle(imgcol, faces[i], Scalar(255, 0, 0));
imFace = imgcol(faces[i]);
resize(imFace, imFace, Size(imFace.cols * 5, imFace.rows * 5));
faces[i] = Rect(faces[i].x = 0, faces[i].y = 0, faces[i].width * 5,
(faces[i].height) * 5);
}
vector< vector<Point2f> > shapes;
//vector < Rect > measures;
if (facemark->fit(imFace, faces, shapes)) //fiiting predef shapes in faces// // imface is the size of faces
{
for (unsigned long i = 0; i < faces.size(); i++) {
for (unsigned long k = 0; k < shapes[i].size(); k++) {
cv::circle(imFace, shapes[i][k], 5, cv::Scalar(0, 0, 255), FILLED);
}
}
}
namedWindow("Detected_shape");
imshow("Detected_shape", imFace);
waitKey(5);
}
else {
cout << "Faces not detected." << endl;
}
}
int main()
{
facemark = FacemarkLBF::create();
facemark->loadModel("C:/Dev/HeadPose/HeadPose/lbfmodel.yml");
faceDetector.load("D:/opencv/build/install/etc/haarcascades/haarcascade_frontalface_alt2.xml");
mouth.load("D:/opencv/build/install/etc/haarcascades/haarcascade_smile.xml");
eye.load("D:/opencv/build/install/etc/haarcascades/haarcascade_eye.xml");
cout << "Loaded model" << endl;
Mat frame, grayframe, testframe, faceROI;
int x_axis, y_axis;
namedWindow("Detecting");
VideoCapture cap(0); //1 for diff cam
while (1)
{
cap.read(frame);
if (!cap.read(frame))
{
cout << "an error while taking the frame from cap" << endl;
}
//face
vector<Rect> faces;
Mat frame_gray;
Mat crop;
Mat res;
Mat gray;
string text;
stringstream sstm;
cvtColor(frame, grayframe, CV_BGR2GRAY);
equalizeHist(grayframe, testframe);
faceDetector.detectMultiScale(testframe, faces, 1.1, 3, CASCADE_SCALE_IMAGE, Size(30, 30));
Rect roi_b;
Rect roi_c;
size_t ic = 0;
int ac = 0;
size_t ib = 0;
int ab = 0;
for (int ic = 0; ic < faces.size(); ic++)
{
roi_b.x = faces[ib].x;
roi_b.y = faces[ib].y;
roi_b.width = (faces[ib].width);
roi_b.height = (faces[ib].height);
crop = frame(roi_b);
resize(crop, res, Size(128, 128), 0, 0, INTER_LINEAR);
cvtColor(crop, gray, COLOR_BGR2GRAY);
stringstream ssfn;
filename = "C:\\Users\\Hp\\Desktop\\Faces\\";
ssfn << filename.c_str() << name <<"_"<< roi_b.width<<"_"<< roi_b.height << ".jpg";
filename = ssfn.str();
imwrite(filename, res);
rectangle(frame, faces[ic], Scalar(255, 0, 255), 2, 8, 0);
Mat face = frame(faces[ic]);
cvtColor(face, face, CV_BGR2GRAY);
//mouth
vector <Rect> mouthi;
mouth.detectMultiScale(face, mouthi);
for (int k = 0; k < mouthi.size(); k++)
{
Point pt1(mouthi[0].x + faces[ic].x, mouthi[0].y + faces[ic].y);
Point pt2(pt1.x + mouthi[0].width, pt1.y + mouthi[0].height);
rectangle(frame, pt1, pt2, Scalar(255, 0, 0), 1, 8, 0);
}
//eyes
faceROI = frame(faces[ic]);//Taking area of the face as Region of Interest for eyes//
vector<Rect>eyes;//declaring a vector named eyes//
eye.detectMultiScale(faceROI, eyes, 1.1, 3, 0 | CASCADE_SCALE_IMAGE, Size(5, 5)); //detect eyes in every face//
/*eye1.detectMultiScale(faceROI, eyes, 1.1, 3, 0 | CASCADE_SCALE_IMAGE, Size(5, 5));*/
for (size_t j = 0; j < eyes.size(); j++)
{ //for locating eyes//
Point center(faces[ic].x + eyes[j].x + eyes[j].width * 0.5, faces[ic].y + eyes[j].y + eyes[j].height * 0.5);//getting the centers of both eyes//
int radius = cvRound((eyes[j].width + eyes[j].height) * 0.25); //declaring radius of the eye enclosing circles//
// cout << "radius" << radius << endl;
circle(frame, center, radius, Scalar(255, 0, 0), 1, 8, 0);//drawing circle around both eyes//
x_axis = eyes[j].x;//storing x axis location of eyes in x_axis//
y_axis = eyes[j].y;//storing y axis location of eyes in y_axis//
cout << "Position of the eyes is:" << "(" << x_axis << "," << y_axis << ")" << endl;//showing co-ordinate values//
}
}
sstm << "Crop area size: " << roi_b.width << "x" << roi_b.height << " Filename: " << filename;
text = sstm.str();
if (!crop.empty()) {
imshow("detected", crop);
}
else destroyWindow("detected");
cout << "Name\n";
cin >> name;
Mat img; //image containers
Mat imgbw;
cap >> img; //image from webcam
resize(img, img, Size(460, 460), 0, 0, INTER_LINEAR_EXACT);
cvtColor(img, imgbw, COLOR_BGR2GRAY);
process(imgbw, img);
imshow("Detecting", frame);
if (waitKey(30) == 27) {
break;
}
}
return 0;
}
I'm trying to calculate the mass center of images using OpenCV and I got errors, as you can see in the images (the mass center must not be to closest of any side in this cases). Also, I got mass centers that depends of the rotation and that's incorrect.
Next, you can see the code, input image and output image.
I tried with different example codes, and the results are the same.
Output image: Mass center calculated by the program
Input image: Image Input
Example code:
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace cv;
using namespace std;
Mat src; Mat srcGray;
RNG rng(12345);
int main(int argc, char **argv)
{
// Load source image and convert it to gray
src = imread(argv[1], 1);
// Convert image to gray and blur it
cvtColor(src, srcGray, CV_BGR2GRAY);
blur(srcGray, srcGray, Size(3, 3));
Mat srcThresh;
double otsu;
otsu = threshold(srcGray, srcThresh, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
Mat cannyOut;
Canny(srcGray, cannyOut, otsu, otsu * 1 / 2, 3, 1);
// Find contours
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(cannyOut, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
// Get the moments
vector<Moments> mu(contours.size());
for (int i = 0; i < contours.size(); i++)
{
mu[i] = moments(contours[i], false);
}
// Get the mass centers:
vector<Point2f> mc(contours.size());
for (int i = 0; i < contours.size(); i++)
{
mc[i] = Point2f(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);
}
// Draw contours
Mat drawing = Mat::zeros(cannyOut.size(), CV_8UC3);
string sObjectNumber; // string which will contain the result
ostringstream sContourNumber; // stream used for the conversion
for (int i = 0; i< contours.size(); i++)
{
// drawing.setTo(Scalar(0.0,0.0,0.0));
sContourNumber << i;
sObjectNumber = sContourNumber.str(); // Convert int to string
Point pCoordinates(mc[i].x + 3, mc[i].y - 3); // Text's coordinates (A little bit off from mass center)
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());
circle(drawing, mc[i], 4, color, -1, 8, 0); // Draw mass center
putText(drawing, sObjectNumber, pCoordinates, CV_FONT_HERSHEY_COMPLEX, 1, color, 2, 8); // Write object number
sContourNumber.str(""); // Clear string
sContourNumber.clear(); // Clear any error flags
// imshow("Contours", drawing);
// waitKey();
}
double hu[7];
for (int i = 0; i < contours.size(); i++)
{
cout << "Contour: " << i << " Area: " << contourArea(contours[i]) << " Length: " << arcLength(contours[i], true) << "\n";
for (int j = 0; j < 7; j++)
{
HuMoments(mu[i], hu);
cout << "Contour: " << i << " Hu: " << j << " Result: " << hu[j] << "\n";
}
cout << "\n";
}
imshow("Contours", drawing);
waitKey(0);
return(0);
}
Very thanks for all!
Diego
I am trying to make a hand recognition system but when i used grayscale for cvtColor, i get debug assertion fail but when i use HSV the code works fine. Can you resolve this ? I am a newbie in opencv.
#include "stdafx.h"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/objdetect.hpp"
#include < opencv2\opencv.hpp>
#include < stdio.h>
#include <iostream>
using namespace std;
using namespace cv;
int thresh = 100;
int findBiggestContour(vector<vector<Point> > contours){
int indexOfBiggestContour = -1;
int sizeOfBiggestContour = 0;
for (int i = 0; i < contours.size(); i++){
if (contours[i].size() > sizeOfBiggestContour){
sizeOfBiggestContour = contours[i].size();
indexOfBiggestContour = i;
}
}
return indexOfBiggestContour;
}
void shifcontour(vector<Point>& contour, int x, int y)
{
for (size_t i = 0; i<contour.size(); i++)
{
contour[i].x += x;
contour[i].y += y;
}
}
int main()
{
cout << "beginning";
VideoCapture cap("pathaka.MP4");
if (!cap.isOpened()) // check if we succeeded
return -1;
Ptr<BackgroundSubtractor> pMOG2 = createBackgroundSubtractorMOG2();
for (;;)
{
Mat original, img;
cap >> img;
imshow("Source", img);
Mat hsv;
cvtColor(img, hsv, CV_BGR2GRAY);
Mat bw;
inRange(hsv, Scalar(0, 30, 80), Scalar(20, 150, 255), bw);
GaussianBlur(bw, bw, Size(7, 7), 1.5, 1.5);
Canny(bw, bw, 0, 30, 3);
vector<vector<Point> > contours;
vector<vector<Point> > convex_hull;
vector<Vec4i> hierarchy;
int erosion_type = MORPH_ELLIPSE;
int erosion_size = 0;
Mat element = getStructuringElement(erosion_type,
Size(2 * erosion_size + 1, 2 * erosion_size + 1),
Point(erosion_size, erosion_size));
dilate(bw, bw, element);
findContours(bw, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
int s = findBiggestContour(contours);
Mat drawing = Mat::zeros(img.size(), CV_8UC1);
dilate(drawing, drawing, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));
dilate(drawing, drawing, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));
std::vector<cv::Point> cnt;
cnt = contours[s];
Moments M;
M = cv::moments(cnt);
cv::Point result;
result = cv::Point(M.m10 / M.m00, M.m01 / M.m00);
Point center(drawing.cols / 2, drawing.rows / 2);
cv::circle(drawing, center, 3, Scalar(255, 255, 255), -1, 8, 0);
int x;
if (result.x > center.x)
{
x = result.x - center.x;
x = -x;
}
else
{
x = result.x - center.x;
}
int y;
if (result.y < center.y)
{
y = center.y - result.y;
}
else
{
y = center.y - result.y;
}
cout << "x:" << x << endl;
cout << "y: " << y << endl;
shifcontour(contours[s], x, y);
drawContours(drawing, contours, s, Scalar(255), -1, 8, hierarchy, 0, Point());
imshow("Hsv", drawing);
if (waitKey(30) >= 0) break;
}
return 0;
}
I think the problem is:
findContours(bw, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
contours now may have something inside, but it could be empty, right? Then, you do this:
int s = findBiggestContour(contours);
If contours.size() == 0, then s == -1, correct?
But after that, you do this:
std::vector<cv::Point> cnt;
cnt = contours[s];
If contours is empty, contours[-1] throws vector subscript out of range.
You should check if (s != -1) before using contours[s], ok?
Perhaps you should process the contours only if there is any, like this:
findContours(bw, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
if (contours.size() > 0) {
int s = findBiggestContour(contours);
Mat drawing = Mat::zeros(img.size(), CV_8UC1);
// these dilates are useless, because drawing is an empty image!
dilate(drawing, drawing, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));
dilate(drawing, drawing, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));
std::vector<cv::Point> cnt = contours[s];
Moments M = cv::moments(cnt);
Point result = cv::Point(M.m10 / M.m00, M.m01 / M.m00);
Point center(drawing.cols / 2, drawing.rows / 2);
circle(drawing, center, 3, Scalar(255, 255, 255), -1, 8, 0);
int x;
if (result.x > center.x) {
x = result.x - center.x;
x = -x;
} else {
x = result.x - center.x;
}
// is this correct? y has the same value in both cases...
int y;
if (result.y < center.y) y = center.y - result.y;
else y = center.y - result.y;
cout << "x:" << x << endl;
cout << "y: " << y << endl;
shifcontour(contours[s], x, y);
drawContours(drawing, contours, s, Scalar(255), -1, 8, hierarchy, 0, Point());
imshow("Hsv", drawing);
}
I am currently trying to use OpenCV version 2.4.10 to detect red colored cups. I am new to OpenCV so I am starting with example code and trying to work my way from there. My idea was to utilize thresholding to first find any red objects on the frame. From there I wish to find the convex hull of those objects to detect which ones are actually cups (have a smaller bottom contour line than top). I am having trouble combining the convex hull code with the thresholding code that I had working prior however. Can someone tell me what I am doing wrong and also point me in the right direction if my approach to this project seems off? Thank you!
Here is my code so far:
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace cv;
using namespace std;
int thresh = 100;
int max_thresh = 255;
RNG rng(12345);
int main(int argc, char** argv)
{
cout << "Program Starts Here." << endl;
VideoCapture cap(0); //capture the video from webcam
if (!cap.isOpened()) // if not success, exit program
{
cout << "Cannot open the web cam" << endl;
return -1;
}
//namedWindow("Control", CV_WINDOW_AUTOSIZE); //create a window called "Control"
int iLowH = 170;
int iHighH = 179;
int iLowS = 150;
int iHighS = 255;
int iLowV = 60;
int iHighV = 255;
//Create trackbars in "Control" window
// createTrackbar("LowH", "Control", &iLowH, 179); //Hue (0 - 179)
// createTrackbar("HighH", "Control", &iHighH, 179);
// createTrackbar("LowS", "Control", &iLowS, 255); //Saturation (0 - 255)
// createTrackbar("HighS", "Control", &iHighS, 255);
// createTrackbar("LowV", "Control", &iLowV, 255);//Value (0 - 255)
// createTrackbar("HighV", "Control", &iHighV, 255);
int iLastX = -1;
int iLastY = -1;
//Capture a temporary image from the camera
Mat imgTmp;
cap.read(imgTmp);
//Create a black image with the size as the camera output
Mat imgLines = Mat::zeros(imgTmp.size(), CV_8UC3);;
while (true)
{
Mat imgOriginal;
bool bSuccess = cap.read(imgOriginal); // read a new frame from video
if (!bSuccess) //if not success, break loop
{
cout << "Cannot read a frame from video stream" << endl;
break;
}
Mat imgHSV;
cvtColor(imgOriginal, imgHSV, COLOR_BGR2HSV); //Convert the captured frame from BGR to HSV
Mat imgThresholded;
inRange(imgHSV, Scalar(iLowH, iLowS, iLowV), Scalar(iHighH, iHighS, iHighV), imgThresholded); //Threshold the image
//morphological opening (removes small objects from the foreground)
erode(imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));
dilate(imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));
//morphological closing (removes small holes from the foreground)
dilate(imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));
erode(imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));
/////////////////////////////////////////////////////////////////////////////////////////////////////
//////START OF ADDED CONVEX HULL CODE
Mat threshold_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
/// Detect edges using Threshold
threshold(imgThresholded, threshold_output, thresh, 255, THRESH_BINARY);
/// Find contours
findContours(threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE,
Point(0, 0));
/// Find the convex hull object for each contour
vector<vector<Point> >hull(contours.size());
for (int i = 0; i < contours.size(); i++)
{
convexHull(Mat(contours[i]), hull[i], false);
}
/// Draw contours + hull results
Mat drawing = Mat::zeros(threshold_output.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, 1, 8, vector<Vec4i>(), 0, Point());
drawContours(drawing, hull, i, color, 1, 8, vector<Vec4i>(), 0, Point());
}
/// Show in a window
namedWindow("Convex Hull", CV_WINDOW_AUTOSIZE);
imshow("Convex Hull", drawing);
///END OF ADDED CODE
/////////////////////////////////////////////////////////////////////////////////////////////////////
//Calculate the moments of the thresholded image
Moments oMoments = moments(imgThresholded);
double dM01 = oMoments.m01;
double dM10 = oMoments.m10;
double dArea = oMoments.m00;
// if the area <= 10000, I consider that the there are no object in the image and it's because of the noise, the area is not zero
if (dArea > 10000)
{
//calculate the position of the object
int posX = dM10 / dArea;
int posY = dM01 / dArea;
cout << "X = " << posX << endl;
cout << "Y = " << posY << endl;
if (posX > 275 && posX < 325){
cout << "Object Straight Ahead." << endl;
}
else if (posX < 275){
cout << "Turn Left." << endl;
}
else if (posX > 325){
cout << "Turn Right." << endl;
}
if (iLastX >= 0 && iLastY >= 0 && posX >= 0 && posY >= 0)
{
//Draw a red line from the previous point to the current point (for visual debugging)
line(imgLines, Point(posX, posY), Point(iLastX, iLastY), Scalar(0, 0, 255), 2);
}
iLastX = posX;
iLastY = posY;
}
imshow("Thresholded Image", imgThresholded); //show the thresholded image
imgOriginal = imgOriginal + imgLines;
imshow("Original", imgOriginal); //show the original image
if (waitKey(30) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
{
cout << "esc key is pressed by user" << endl;
break;
}
}
return 0;
}
I'm having Heap corruption exception while compiling this code which I found on the internet. I'm a beginner and I don't know how to solve the problem.
the exception occurred in the following line:
matcher.knnMatch(desObject, des_image, matches, 2);
Could someone tell me what should I replace this line of code with?
The complete source code:
cv::initModule_nonfree();
// turn performance analysis functions on if testing = true
bool testing = false;
double t; // timing variable
// load training image
Mat object = imread("boo2.png", CV_LOAD_IMAGE_GRAYSCALE);
if (!object.data) {
cout << "Can't open image";
return -1;
}
namedWindow("Good Matches", CV_WINDOW_AUTOSIZE);
// SURF Detector, and descriptor parameters
int minHess = 3000;
vector<KeyPoint> kpObject, kpImage;
Mat desObject, desImage;
// Performance measures calculations for report
if (testing) {
cout << object.rows << " " << object.cols << endl;
// calculate integral image
Mat iObject;
integral(object, iObject);
imshow("Good Matches", iObject);
imwrite("boo2.png", iObject);
cvWaitKey(0);
// calculate number of interest points, computation time as f(minHess)
int minHessVector[] = {100, 500, 1000, 1500, 2000, 2500, 3000,
3500, 4000, 4500, 5000, 5500, 6000, 6500,
7000, 7500, 8000, 8500, 9000, 9500, 10000};
int minH;
std::ofstream file;
file.open("C:/School/Image Processing/TimingC.csv", std::ofstream::out);
for (int i = 0; i < 20; i++) {
minH = minHessVector[i];
t = (double)getTickCount();
SurfFeatureDetector detector(minH);
detector.detect(object, kpObject);
t = ((double)getTickCount() - t) / getTickFrequency();
file << minHess << "," << kpObject.size() << "," << t << ",";
cout << t << " " << kpObject.size() << " " << desObject.size() << endl;
t = (double)getTickCount();
SurfDescriptorExtractor extractor;
extractor.compute(object, kpObject, desObject);
t = ((double)getTickCount() - t) / getTickFrequency();
file << t << endl;
}
file.close();
// Display keypoints on training image
Mat interestPointObject = object;
for (unsigned int i = 0; i < kpObject.size(); i++) {
if (kpObject[i].octave) {
circle(interestPointObject, kpObject[i].pt, kpObject[i].size, 0);
string octaveS;
switch (kpObject[i].octave) {
case 0:
octaveS = "0";
break;
case 1:
octaveS = '1';
break;
case 2:
octaveS = '2';
break;
default:
break;
}
putText(interestPointObject, octaveS, kpObject[i].pt,
FONT_HERSHEY_COMPLEX_SMALL, 1, cvScalar(0, 0, 250), 1, CV_AA);
}
}
imshow("Good Matches", interestPointObject);
imwrite("C:/School/Image Processing/bookIP2.jpg", interestPointObject);
cvWaitKey(0);
}
// SURF Detector, and descriptor parameters, match object
// initialization
minHess = 2000;
SurfFeatureDetector detector(minHess);
detector.detect(object, kpObject);
SurfDescriptorExtractor extractor;
extractor.compute(object, kpObject, desObject);
FlannBasedMatcher matcher;
// Initialize video and display window
VideoCapture cap(1); // camera 1 is webcam
if (!cap.isOpened()) return -1;
// Object corner points for plotting box
vector<Point2f> obj_corners(4);
obj_corners[0] = cvPoint(0, 0);
obj_corners[1] = cvPoint(object.cols, 0);
obj_corners[2] = cvPoint(object.cols, object.rows);
obj_corners[3] = cvPoint(0, object.rows);
// video loop
char escapeKey = 'k';
double frameCount = 0;
float thresholdMatchingNN = 0.7;
unsigned int thresholdGoodMatches = 4;
unsigned int thresholdGoodMatchesV[] = {4, 5, 6, 7, 8, 9, 10};
for (int j = 0; j < 7; j++) {
thresholdGoodMatches = thresholdGoodMatchesV[j];
// thresholdGoodMatches=8;
cout << thresholdGoodMatches << endl;
if (true) {
t = (double)getTickCount();
}
while (escapeKey != 'q') {
frameCount++;
Mat frame;
Mat image;
cap >> frame;
cvtColor(frame, image, CV_RGB2GRAY);
Mat des_image, img_matches, H;
vector<KeyPoint> kp_image;
vector<vector<DMatch>> matches;
vector<DMatch> good_matches;
vector<Point2f> obj;
vector<Point2f> scene;
vector<Point2f> scene_corners(4);
detector.detect(image, kp_image);
extractor.compute(image, kp_image, des_image);
matcher.knnMatch(desObject, des_image, matches, 2);
for (int i = 0; i < min(des_image.rows - 1, (int)matches.size()); i++)
// THIS LOOP IS SENSITIVE TO SEGFAULTS
{
if ((matches[i][0].distance <
thresholdMatchingNN * (matches[i][1].distance)) &&
((int)matches[i].size() <= 2 && (int)matches[i].size() > 0)) {
good_matches.push_back(matches[i][0]);
}
}
// if (good_matches.size()<1)
// good_matches.resize(0,cv::DMatch);
// Draw only "good" matches
drawMatches(object, kpObject, image, kp_image, good_matches, img_matches,
Scalar::all(-1), Scalar::all(-1), vector<char>(),
DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
if (good_matches.size() >= thresholdGoodMatches) {
// Display that the object is found
putText(img_matches, "Object Found", cvPoint(10, 50),
FONT_HERSHEY_COMPLEX_SMALL, 2, cvScalar(0, 0, 250), 1, CV_AA);
for (unsigned int i = 0; i < good_matches.size(); i++) {
// Get the keypoints from the good matches
obj.push_back(kpObject[good_matches[i].queryIdx].pt);
scene.push_back(kp_image[good_matches[i].trainIdx].pt);
}
H = findHomography(obj, scene, CV_RANSAC);
perspectiveTransform(obj_corners, scene_corners, H);
// Draw lines between the corners (the mapped object in the scene
// image )
line(img_matches, scene_corners[0] + Point2f(object.cols, 0),
scene_corners[1] + Point2f(object.cols, 0), Scalar(0, 255, 0), 4);
line(img_matches, scene_corners[1] + Point2f(object.cols, 0),
scene_corners[2] + Point2f(object.cols, 0), Scalar(0, 255, 0), 4);
line(img_matches, scene_corners[2] + Point2f(object.cols, 0),
scene_corners[3] + Point2f(object.cols, 0), Scalar(0, 255, 0), 4);
line(img_matches, scene_corners[3] + Point2f(object.cols, 0),
scene_corners[0] + Point2f(object.cols, 0), Scalar(0, 255, 0), 4);
} else {
putText(img_matches, "", cvPoint(10, 50), FONT_HERSHEY_COMPLEX_SMALL, 3,
cvScalar(0, 0, 250), 1, CV_AA);
}
// Show detected matches
imshow("Good Matches", img_matches);
escapeKey = cvWaitKey(10);
// imwrite("C:/School/Image Processing/bookIP3.jpg", img_matches);
if (frameCount > 10) escapeKey = 'q';
}
// average frames per second
if (true) {
t = ((double)getTickCount() - t) / getTickFrequency();
cout << t << " " << frameCount / t << endl;
cvWaitKey(0);
}
frameCount = 0;
escapeKey = 'a';
}
// Release camera and exit
cap.release();