CV_EXPORTS_W void matchTemplate( InputArray image, InputArray templ,
OutputArray result, int method );
-enum { CC_STAT_LEFT=0, CC_STAT_TOP=1, CC_STAT_WIDTH=2, CC_STAT_HEIGHT=3, CC_STAT_CX=4, CC_STAT_CY=5, CC_STAT_AREA=6, CC_STAT_INTEGRAL_X=7, CC_STAT_INTEGRAL_Y=8, CC_STAT_MAX = 9};
+enum { CC_STAT_LEFT=0, CC_STAT_TOP=1, CC_STAT_WIDTH=2, CC_STAT_HEIGHT=3, CC_STAT_AREA=4, CC_STAT_MAX = 5};
//! computes the connected components labeled image of boolean image I with 4 or 8 way connectivity - returns N, the total
//number of labels [0, N-1] where 0 represents the background label. L's value type determines the label type, an important
//consideration based on the total number of labels or alternatively the total number of pixels.
-CV_EXPORTS_W int connectedComponents(InputArray image, OutputArray labels, int connectivity = 8);
-CV_EXPORTS_W int connectedComponentsWithStats(InputArray image, OutputArray labels, OutputArray stats, int connectivity = 8);
+CV_EXPORTS_W int connectedComponents(InputArray image, OutputArray labels, int connectivity = 8, int ltype=CV_32S);
+CV_EXPORTS_W int connectedComponentsWithStats(InputArray image, OutputArray labels, OutputArray stats, OutputArray centroids, int connectivity = 8, int ltype=CV_32S);
//! mode of the contour retrieval algorithm
}
void finish(){}
};
+ struct Point2ui64{
+ uint64_t x, y;
+ Point2ui64(uint64_t _x, uint64_t _y):x(_x), y(_y){}
+ };
template<typename LabelT>
struct CCStatsOp{
+ OutputArray _mstatsv;
cv::Mat statsv;
- CCStatsOp(OutputArray _statsv): statsv(_statsv.getMat()){
+ OutputArray _mcentroidsv;
+ cv::Mat centroidsv;
+ std::vector<Point2ui64> integrals;
+
+ CCStatsOp(OutputArray _statsv, OutputArray _centroidsv): _mstatsv(_statsv), _mcentroidsv(_centroidsv){
}
inline
void init(const LabelT nlabels){
- statsv = cv::Mat(nlabels, CC_STAT_MAX, cv::DataType<double>::type);
+ _mstatsv.create(cv::Size(nlabels, CC_STAT_MAX), cv::DataType<int>::type);
+ statsv = _mstatsv.getMat();
+ _mcentroidsv.create(cv::Size(nlabels, 2), cv::DataType<double>::type);
+ centroidsv = _mcentroidsv.getMat();
+
for(int l = 0; l < (int) nlabels; ++l){
- double *row = &statsv.at<double>(l, 0);
+ unsigned int *row = (unsigned int *) &statsv.at<int>(l, 0);
row[CC_STAT_LEFT] = std::numeric_limits<LabelT>::max();
row[CC_STAT_TOP] = std::numeric_limits<LabelT>::max();
row[CC_STAT_WIDTH] = std::numeric_limits<LabelT>::min();
row[CC_STAT_HEIGHT] = std::numeric_limits<LabelT>::min();
- row[CC_STAT_CX] = 0;
- row[CC_STAT_CY] = 0;
+ //row[CC_STAT_CX] = 0;
+ //row[CC_STAT_CY] = 0;
row[CC_STAT_AREA] = 0;
- row[CC_STAT_INTEGRAL_X] = 0;
- row[CC_STAT_INTEGRAL_Y] = 0;
}
+ integrals.resize(nlabels, Point2ui64(0, 0));
}
void operator()(int r, int c, LabelT l){
- double *row = &statsv.at<double>(l, 0);
+ int *row = &statsv.at<int>(l, 0);
+ unsigned int *urow = (unsigned int *) row;
if(c > row[CC_STAT_WIDTH]){
row[CC_STAT_WIDTH] = c;
}else{
row[CC_STAT_TOP] = r;
}
}
- row[CC_STAT_INTEGRAL_X] += c;
- row[CC_STAT_INTEGRAL_Y] += r;
- row[CC_STAT_AREA]++;
+ urow[CC_STAT_AREA]++;
+ Point2ui64 &integral = integrals[l];
+ integral.x += c;
+ integral.y += r;
}
void finish(){
for(int l = 0; l < statsv.rows; ++l){
- double *row = &statsv.at<double>(l, 0);
+ unsigned int *row = (unsigned int *) &statsv.at<int>(l, 0);
row[CC_STAT_LEFT] = std::min(row[CC_STAT_LEFT], row[CC_STAT_WIDTH]);
row[CC_STAT_WIDTH] = row[CC_STAT_WIDTH] - row[CC_STAT_LEFT] + 1;
row[CC_STAT_TOP] = std::min(row[CC_STAT_TOP], row[CC_STAT_HEIGHT]);
row[CC_STAT_HEIGHT] = row[CC_STAT_HEIGHT] - row[CC_STAT_TOP] + 1;
- row[CC_STAT_CX] = row[CC_STAT_INTEGRAL_X] / double(row[CC_STAT_AREA]);
- row[CC_STAT_CY] = row[CC_STAT_INTEGRAL_Y] / double(row[CC_STAT_AREA]);
+
+ Point2ui64 &integral = integrals[l];
+ double *centroid = ¢roidsv.at<double>(l, 0);
+ centroid[0] = double(integral.x) / row[CC_STAT_AREA];
+ centroid[1] = double(integral.y) / row[CC_STAT_AREA];
}
}
};
const int G8[4][2] = {{1, -1}, {1, 0}, {1, 1}, {0, -1}};//a, b, c, d neighborhoods
template<typename LabelT, typename PixelT, typename StatsOp = NoOp<LabelT>, int connectivity = 8>
struct LabelingImpl{
- LabelT operator()(InputArray _I, OutputArray _L, StatsOp &sop){
- cv::Mat I = _I.getMat();
- cv::Mat L = _L.getMat();
+ LabelT operator()(const cv::Mat &I, cv::Mat &L, StatsOp &sop){
CV_Assert(L.rows == I.rows);
CV_Assert(L.cols == I.cols);
const int rows = L.rows;
//L's type must have an appropriate depth for the number of pixels in I
template<typename StatsOp>
-int connectedComponents_sub1(InputArray I, OutputArray L, int connectivity, StatsOp &sop){
+static
+int connectedComponents_sub1(const cv::Mat &I, cv::Mat &L, int connectivity, StatsOp &sop){
CV_Assert(L.channels() == 1 && I.channels() == 1);
CV_Assert(connectivity == 8 || connectivity == 4);
return -1;
}
-int connectedComponents(InputArray I, OutputArray L, int connectivity){
- int lDepth = L.depth();
- if(lDepth == CV_8U){
+int connectedComponents(InputArray _I, OutputArray _L, int connectivity, int ltype){
+ const cv::Mat I = _I.getMat();
+ _L.create(I.size(), CV_MAT_TYPE(ltype));
+ cv::Mat L = _L.getMat();
+ if(ltype == CV_8U){
connectedcomponents::NoOp<uint8_t> sop; return connectedComponents_sub1(I, L, connectivity, sop);
- }else if(lDepth == CV_16U){
+ }else if(ltype == CV_16U){
connectedcomponents::NoOp<uint16_t> sop; return connectedComponents_sub1(I, L, connectivity, sop);
- }else if(lDepth == CV_32S){
+ }else if(ltype == CV_32S){
connectedcomponents::NoOp<uint32_t> sop; return connectedComponents_sub1(I, L, connectivity, sop);
}else{
CV_Assert(false);
}
}
-int connectedComponentsWithStats(InputArray I, OutputArray L, OutputArray statsv, int connectivity){
- int lDepth = L.depth();
- if(lDepth == CV_8U){
- connectedcomponents::CCStatsOp<uint8_t> sop(statsv); return connectedComponents_sub1(I, L, connectivity, sop);
- }else if(lDepth == CV_16U){
- connectedcomponents::CCStatsOp<uint16_t> sop(statsv); return connectedComponents_sub1(I, L, connectivity, sop);
- }else if(lDepth == CV_32S){
- connectedcomponents::CCStatsOp<uint32_t> sop(statsv); return connectedComponents_sub1(I, L, connectivity, sop);
+int connectedComponentsWithStats(InputArray _I, OutputArray _L, OutputArray statsv, OutputArray centroids, int connectivity, int ltype){
+ const cv::Mat I = _I.getMat();
+ _L.create(I.size(), CV_MAT_TYPE(ltype));
+ cv::Mat L = _L.getMat();
+ if(ltype == CV_8U){
+ connectedcomponents::CCStatsOp<uint8_t> sop(statsv, centroids); return connectedComponents_sub1(I, L, connectivity, sop);
+ }else if(ltype == CV_16U){
+ connectedcomponents::CCStatsOp<uint16_t> sop(statsv, centroids); return connectedComponents_sub1(I, L, connectivity, sop);
+ }else if(ltype == CV_32S){
+ connectedcomponents::CCStatsOp<uint32_t> sop(statsv, centroids); return connectedComponents_sub1(I, L, connectivity, sop);
}else{
CV_Assert(false);
return 0;