Skip to content

Instantly share code, notes, and snippets.

@ifq
Created May 6, 2013 06:22
Show Gist options
  • Save ifq/5523619 to your computer and use it in GitHub Desktop.
Save ifq/5523619 to your computer and use it in GitHub Desktop.
opencv example of branch-like sym reco.
/**
* @file reco_sym.cpp
* @brief this is a simple try for kin san's pj, which need to reco some
* symbol like tree branch shape.
* @author ifqqfi gmail
*
*/
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
using namespace cv;
/// Global variables
int threshold_value = 100;
int threshold_type = 1;
int const max_value = 255;
int const max_type = 4;
int const max_BINARY_value = 255;
RNG rng(12345);
Mat src, src_gray, dst;
const char* window_name = "Threshold Demo";
const char* trackbar_type = "Type: \n 0: Binary \n 1: Binary Inverted \n 2: Truncate \n 3: To Zero \n 4: To Zero Inverted";
const char* trackbar_value = "Value";
/// Function headers
void Reco_Sym_Process( int, void* );
/**
* @function main
*/
int main( int argc, char** argv )
{
Mat org;
CvSize sz;
/// Load an image
if ( argc < 2) {
cout << "need a pic's filename as a param." << endl;
return 0;
}
org = imread( argv[1], 1 );
// resize pic
if (org.cols > org.rows) {
sz.width = 800;
sz.height = (float)(800 / org.cols) * org.rows;
} else {
sz.width = (float)(800 / org.rows) * org.cols;
sz.height = 800;
}
resize(org, src, sz);
/// Convert the image to Gray
cvtColor( src, src_gray, CV_RGB2GRAY );
/// Create a window to display results
namedWindow( window_name, CV_WINDOW_AUTOSIZE );
/// Create Trackbar to choose type of Threshold
createTrackbar( trackbar_type,
window_name, &threshold_type,
max_type, Reco_Sym_Process );
createTrackbar( trackbar_value,
window_name, &threshold_value,
max_value, Reco_Sym_Process );
/// Call the function to initialize
Reco_Sym_Process( 0, 0 );
/// Wait until user finishes program
for(;;) {
int c;
c = waitKey( 20 );
if( (char)c == 27 ) {
break;
}
}
}
// check if rin is really in rout Rect
static inline int isRectinRect(Rect rin, Rect rout)
{
if ((rout.x <= rin.x) && (rout.y <= rin.y)
&& ((rout.width + rout.x) >= (rin.width + rin.x))
&& ((rout.height + rout.y) >= (rin.height + rin.y))) {
return 1;
}
return 0;
}
// check if r1 and r2 are a pair of frame
// return 1 if r1 is inner rect
// return 2 if r2 is inner rect
// return 0 if not a frame
static inline int framecheck(Rect r1, Rect r2 )
{
int a,b,c,d;
int avg;
a = abs(r1.x - r2.x);
b = abs(r1.y - r2.y);
c = abs(r1.width - r2.width);
d = abs(r1.height - r2.height);
avg = (a + b + c + d)/ 4;
a = abs(a - avg);
b = abs(b - avg);
c = abs(c - avg);
d = abs(d - avg);
if (a > 10 || b > 10 || c > 10 || d>10) {
return 0;
}
if (isRectinRect(r1, r2)) {
// r1 is inner
return 1;
} else if (isRectinRect(r2, r1)) {
// r2 is inner
return 2;
} else {
return 0;
}
}
/**
* @function Reco_Sym_Process
*/
void Reco_Sym_Process( int, void* )
{
/* 0: Binary
1: Binary Inverted
2: Threshold Truncated
3: Threshold to Zero
4: Threshold to Zero Inverted
*/
Mat threshold_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
threshold( src_gray, threshold_output, threshold_value, max_BINARY_value,threshold_type );
findContours( threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
/// Approximate contours to polygons + get bounding rects and circles
vector<vector<Point> > contours_poly( contours.size() );
vector<Rect> boundRect( contours.size() );
vector<Point2f>center( contours.size() );
vector<float>radius( contours.size() );
vector<Rect> frameRect;
vector<Rect> symRect;
for( size_t i = 0; i < contours.size(); i++ )
{ approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true );
boundRect[i] = boundingRect( Mat(contours_poly[i]) );
}
Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 );
cvtColor(threshold_output, drawing, CV_GRAY2BGR);
for( size_t i = 0; i< contours.size(); i++ )
{
// assume sym frame is at least 60% of the pic
if (boundRect[i].width > threshold_output.cols * 0.6 ||
boundRect[i].height > threshold_output.rows * 0.6) {
frameRect.insert(frameRect.begin(), boundRect[i]);
}
}
// for (vector<Rect>::iterator it = frameRect.begin() ;
// it != frameRect.end(); it++){
// Scalar color = Scalar( 255, 0, 0 );
// //rectangle( drawing, it->tl(), it->br(), color, 1, 8, 0 );
// }
// find the frame ! iwood.co.nr
Rect trueRect;
for (int x = 1; x < frameRect.size();x++) {
if (int ret = framecheck(frameRect[x-1], frameRect[x])) {
if(ret==1) {
trueRect = frameRect[x-1];
} else {
trueRect = frameRect[x];
}
cout << "rect " << x << " : " << trueRect << ", "
<< trueRect.size() << ", "
<< trueRect.area() << ", " << ret << endl;
Scalar color = Scalar( 0, 255, 0 );
rectangle( drawing, trueRect.tl(), trueRect.br(), color, 1, 8, 0 );
break;
}
}
// find all rect inside the frame
for (vector<Rect>::iterator it = boundRect.begin() ;
it != boundRect.end(); it++){
if (isRectinRect(*it, trueRect)) {
symRect.insert(symRect.begin(), *it);
}
}
// draw all the rect inside the frame ifqqfi
for (vector<Rect>::iterator it = symRect.begin() ;
it != symRect.end(); it++){
Scalar color = Scalar( 255, 0, 0 );
rectangle( drawing, it->tl(), it->br(), color, 1, 8, 0 );
}
imshow( window_name, drawing );
// imshow( "src", threshold_output);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment