Created
December 30, 2012 15:07
-
-
Save Benjit87/4413198 to your computer and use it in GitHub Desktop.
http://benjithian.sg/2012/12/simple-convex-hull-opencv/
Simple Convex hull. Simple stuff.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
http://benjithian.sg/2012/12/simple-convex-hull-opencv/ | |
Simple Convex hull. Simple stuff. | |
*/ | |
#include <stdio.h> | |
#include <curl/curl.h> | |
#include <sstream> | |
#include <iostream> | |
#include <vector> | |
#include <opencv2/opencv.hpp> | |
//curl writefunction to be passed as a parameter | |
size_t write_data(char *ptr, size_t size, size_t nmemb, void *userdata) { | |
std::ostringstream *stream = (std::ostringstream*)userdata; | |
size_t count = size * nmemb; | |
stream->write(ptr, count); | |
return count; | |
} | |
//Some of the Convex Hull Code from http://docs.opencv.org/doc/tutorials/imgproc/shapedescriptors/hull/hull.html | |
std::vector<std::vector<cv::Point> > contourImg(cv::Mat src) { | |
std::vector<std::vector<cv::Point> > contours; | |
std::vector<cv::Vec4i> hierarchy; | |
cv::findContours(src, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0) ); | |
/// Find the convex hull object for each contour | |
std::vector<std::vector<cv::Point> >hull( contours.size() ); | |
for( int i = 0; i < contours.size(); i++ ) | |
{ | |
cv::convexHull( cv::Mat(contours[i]), hull[i], false ); // false as i want clockwise | |
} | |
int largestarea = 0; // to hold the convex with largest area | |
int areaCount = 0; // hold the hull number with the largest area | |
for(int i = 0; i < hull.size();i++) | |
{ | |
std::vector<cv::Point> hull1 = hull[i]; | |
int area = 0; | |
// I use trapezium formula to find the area of each 2 points | |
// the top trapezium will the + and the bottom trapezium will be - | |
// the difference will be the area | |
for ( int j = 0 ; j < hull1.size()-1 ; j++ ) | |
{ | |
cv::Point point1 = hull1[j]; // current point | |
cv::Point point2 = hull1[j+1]; // next point | |
int area1 = (point1.y + point2.y) * (point1.x-point2.x); // area | |
area += area1; // add them up | |
} | |
if ( largestarea < area ) { largestarea = area;areaCount=i; } //find largest area | |
} | |
std::vector<std::vector<cv::Point> >hull1( 1 ); //create a vector to hold the hull with the largest area | |
hull1.push_back(hull[areaCount]);// insert the largest hull | |
return hull1; | |
} | |
//function to retrieve the image as Cv::Mat data type | |
cv::Mat curlImg() | |
{ | |
CURL *curl; | |
CURLcode res; | |
std::ostringstream stream; | |
curl = curl_easy_init(); | |
curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.0.108:8080/shot.jpg"); //the JPEG Frame url | |
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); // pass the writefunction | |
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &stream); // pass the stream ptr when the writefunction is called | |
res = curl_easy_perform(curl); // start curl | |
std::string output = stream.str(); // convert the stream into a string | |
curl_easy_cleanup(curl); // cleanup | |
std::vector<char> data = std::vector<char>( output.begin(), output.end() ); //convert string into a vector | |
cv::Mat data_mat = cv::Mat(data); // create the cv::Mat datatype from the vector | |
cv::Mat image = cv::imdecode(data_mat,1); //read an image from memory buffer | |
return image; | |
} | |
int main(void) | |
{ | |
cv::namedWindow( "Image output", CV_WINDOW_AUTOSIZE ); | |
int i = 1; | |
cv::Mat image = curlImg(); // get the image frame | |
while(1) | |
{ | |
if ( i == 1 ) // Update the background every 100*33ms | |
{ | |
i = 100; | |
image = curlImg(); // get the image frame | |
cv::cvtColor(image,image, CV_BGR2GRAY);//Convert to GreyScale | |
} | |
i--; | |
char c = cvWaitKey(33); // sleep for 33ms or till a key is pressed (put more then ur camera framerate mine is 30ms) | |
cv::Mat image2 = curlImg(); // the image that is constantly being updated | |
cv::Mat image3 = image2.clone(); | |
cv::cvtColor(image2,image2, CV_BGR2GRAY);//Convert to GreyScale | |
cv::absdiff(image,image2,image2);// Absolute differences between the 2 images | |
cv::blur(image2,image2,cv::Size(10,10)); // Try to elimite stray patch | |
cv::threshold(image2,image2,5,255,CV_THRESH_BINARY); // set threshold to ignore small differences you can also use inrange function | |
std::vector<std::vector<cv::Point> > hull = contourImg(image2); | |
/// Draw contours + hull results | |
for( int i = 0; i< hull.size(); i++ ) | |
{ | |
cv::Scalar color = cv::Scalar( 255, 0, 0 ); // blue | |
cv::drawContours( image3, hull, i, color, 3, 8, std::vector<cv::Vec4i>(), 0, cv::Point() ); // draw the hull | |
} | |
//cv::Mat image3 = contourImg(image2); | |
cv::imshow("Image output",image3); // display image | |
c = cvWaitKey(33); | |
if ( c == 27 ) break; // break if ESC is pressed | |
} | |
cv::destroyWindow("Image output"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment