Skip to content

Instantly share code, notes, and snippets.

@Benjit87
Created December 30, 2012 15:07
Show Gist options
  • Save Benjit87/4413198 to your computer and use it in GitHub Desktop.
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.
*/
#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