//! Calculate contour points from crack codes t_PointList CBlobContour::GetContourPoints() { // it is calculated? if( m_contourPoints != NULL ) return m_contourPoints; if ( m_contour == NULL || m_contour->total <= 0 ) { return NULL; } CvSeq *tmpPoints; CvSeqReader reader; CvSeqWriter writer; CvPoint actualPoint; CvRect boundingBox; // if aproximation is different than simple extern perimeter will not work tmpPoints = cvApproxChains( m_contour, m_parentStorage, CV_CHAIN_APPROX_NONE); // apply an offset to contour points to recover real coordinates cvStartReadSeq( tmpPoints, &reader); m_contourPoints = cvCreateSeq( tmpPoints->flags, tmpPoints->header_size, tmpPoints->elem_size, m_parentStorage ); cvStartAppendToSeq(m_contourPoints, &writer ); // also calculate bounding box of the contour to allow cvPointPolygonTest // work correctly on the generated polygon boundingBox.x = boundingBox.y = 10000; boundingBox.width = boundingBox.height = 0; for( int i=0; i< tmpPoints->total; i++) { CV_READ_SEQ_ELEM( actualPoint, reader); actualPoint.x += m_startPoint.x; actualPoint.y += m_startPoint.y; boundingBox.x = MIN( boundingBox.x, actualPoint.x ); boundingBox.y = MIN( boundingBox.y, actualPoint.y ); boundingBox.width = MAX( boundingBox.width, actualPoint.x ); boundingBox.height = MAX( boundingBox.height, actualPoint.y ); CV_WRITE_SEQ_ELEM( actualPoint, writer ); } cvEndWriteSeq( &writer ); cvClearSeq( tmpPoints ); // assign calculated bounding box ((CvContour*)m_contourPoints)->rect = boundingBox; return m_contourPoints; }
/* * call-seq: * approx_chains(<i>[approx_chain_option]</i>) -> cvcontour * * Approximates Freeman chain(s) with polygonal curve. * <i>approx_chain_option</i> should be Hash include these keys. * :method - Approximation method. * :approx_none - translate all the points from the chain code into points; * :approx_simple(default) - compress horizontal, vertical, and diagonal segments, that is, * the function leaves only their ending points. * :approx_tc89_l1 * :approx_tc89_kcos - apply one of the flavors of Teh-Chin chain approximation algorithm. * If set the difference between the current pixel and seed pixel is considered, * otherwise difference between neighbor pixels is considered (the range is floating). * :parameter - Method parameter (not used now). * :minimal_perimeter (default 0) * Approximates only those contours whose perimeters are not less than minimal_perimeter. Other chains are removed from the resulting structure. * :recursive (default false) * If not nil or false, the function approximates all chains that access can be obtained to * from self by h_next or v_next links. If 0, the single chain is approximated. * */ VALUE rb_approx_chains(int argc, VALUE *argv, VALUE self) { VALUE approx_chain_option; rb_scan_args(argc, argv, "01", &approx_chain_option); approx_chain_option = APPROX_CHAIN_OPTION(approx_chain_option); VALUE storage = cCvMemStorage::new_object(); CvSeq *seq = cvApproxChains(CVSEQ(self), CVMEMSTORAGE(storage), APPROX_CHAIN_METHOD(approx_chain_option), APPROX_CHAIN_PARAMETER(approx_chain_option), APPROX_CHAIN_MINIMAL_PERIMETER(approx_chain_option), APPROX_CHAIN_RECURSIVE(approx_chain_option)); if (seq && seq->total > 0) { return cCvSeq::new_sequence(cCvChain::rb_class(), seq, cCvPoint::rb_class(), storage); } return Qnil; }