I have wrote the following shape code, but i'm having some difficulties regarding how it works. I want to be able to track the shape of the object whilst the object is moving, but at the moment the code below only tracks the shape of the object whilst the object is standstill and why whilst it is moving very slowly. Anyone knows any modifications i can make to the code to make it track objects moving quite fast? Thanks very much in advance.
/**
* Simple shape detector program.
* It loads an image and tries to find simple shapes (rectangle, triangle, circle, etc) in it.
* This program is a modified version of squares.cpp
found in the OpenCV sample dir.
*/
include <opencv2 highgui="" highgui.hpp="">
include <opencv2 imgproc="" imgproc.hpp="">
include <cmath>
include <iostream>
include <sstream>
include <string>
include <iostream>
include <opencv highgui.h="">
include <opencv cv.h="">
include <opencv2 imgproc="" imgproc.hpp="">
include <fcntl.h>
include <stdio.h>
include <unistd.h>
/** * Helper function to find a cosine of angle between vectors * from pt0->pt1 and pt0->pt2 */ cv::Mat dst2;
static double angle(cv::Point pt1, cv::Point pt2, cv::Point pt0) { double dx1 = pt1.x - pt0.x; double dy1 = pt1.y - pt0.y; double dx2 = pt2.x - pt0.x; double dy2 = pt2.y - pt0.y; return (dx1dx2 + dy1dy2)/sqrt((dx1dx1 + dy1dy1)(dx2dx2 + dy2*dy2) + 1e-10);
}
/** * Helper function to display text in the center of a contour */ void setLabel(cv::Mat& im, const std::string label, std::vector<cv::point>& contour) { int fontface = cv::FONT_HERSHEY_SIMPLEX; double scale = 0.4; int thickness = 1; int baseline = 0;
cv::Size text = cv::getTextSize(label, fontface, scale, thickness, &baseline); cv::Rect r = cv::boundingRect(contour);
cv::Point pt(r.x + ((r.width - text.width) / 2), r.y + ((r.height + text.height) / 2)); cv::rectangle(im, pt + cv::Point(0, baseline), pt + cv::Point(text.width, -text.height), CV_RGB(255,255,255), CV_FILLED); cv::putText(im, label, pt, fontface, scale, CV_RGB(0,0,0), thickness, 8); }
int main() { //cvNamedWindow("Camera_Output", 1); //Create window CvCapture* capture = cvCaptureFromCAM(1); //Capture using any camera connected to your system
while(1){ IplImage * img = cvQueryFrame(capture); cvSmooth(img, img, CV_GAUSSIAN,3,3);
//show the original image //cvNamedWindow("Raw"); //cvShowImage("Raw",img);
cv::Mat src(img);
//cv::Mat src = cv::imread("/home/john/Desktop/basic-shapes.png"); //if (src.empty()) //return -1;
// Convert to grayscale cv::Mat gray; cv::cvtColor(src, gray, CV_BGR2GRAY);
// Use Canny instead of threshold to catch squares with gradient shading cv::Mat bw; cv::Canny(gray, bw, 0, 50, 5);
// Find contours std::vector<std::vector<cv::point> > contours; cv::findContours(bw.clone(), contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
std::vector<cv::point> approx; cv::Mat dst = src.clone();
for (int i = 0; i < contours.size(); i++) { // Approximate contour with accuracy proportional // to the contour perimeter cv::approxPolyDP(cv::Mat(contours[i]), approx, cv::arcLength(cv::Mat(contours[i]), true)*0.04, true);
// Skip small or non-convex objects if (std::fabs(cv::contourArea(contours[i])) < 500 || !cv::isContourConvex(approx)) continue;
if (approx.size() == 3) {
//setLabel(dst, "TRI", contours[i]); // Triangles }
else if (approx.size() >= 4 && approx.size() <= 6) { // Number of vertices of polygonal curve int vtc = approx.size();
// Get the cosines of all corners std::vector<double> cos; for (int j = 2; j < vtc+1; j++) cos.push_back(angle(approx[j%vtc], approx[j-2], approx[j-1]));
// Sort ascending the cosine values std::sort(cos.begin(), cos.end());
// Get the lowest and the highest cosine double mincos = cos.front(); double maxcos = cos.back();
// Use the degrees obtained above and the number of vertices // to determine the shape of the contour if (vtc == 4 && mincos >= -0.1 && maxcos <= 0.3) { // Detect rectangle or square cv::Rect r = cv::boundingRect(contours[i]); double ratio = std::abs(1 - (double)r.width / r.height); setLabel(dst, ratio <= 0.02 ? "SQU" : "RECT", contours[i]); } //else if (vtc == 4 && mincos >= -0.1 && maxcos <= 0.3) //setLabel(dst, "RECT", contours[i]); else if (vtc == 5 && mincos >= -0.34 && maxcos <= -0.27) setLabel(dst, "PENTA", contours[i]); else if (vtc == 6 && mincos >= -0.55 && maxcos <= -0.45) setLabel(dst, "HEXA", contours[i]); } else { // Detect and label circles double area = cv::contourArea(contours[i]); cv::Rect r = cv::boundingRect(contours[i]); int radius = r.width / 2;
if (std::abs(1 - ((double)r.width / r.height)) <= 0.2 && std::abs(1 - (area / (CV_PI * std::pow(radius, 2)))) <= 0.2) setLabel(dst, "CIR", contours[i]); } }
cv::imshow("dst", dst); //cv::imshow("src", src);
cv::waitKey(10); }
return 0; }