Commit e70b3ef5 authored by Jason Newton's avatar Jason Newton

use a ltype parameter to determine result Label image type; export stats with…

use a ltype parameter to determine result Label image type; export stats with differening types over different outputarrays
parent 6a4d881a
......@@ -1091,13 +1091,13 @@ enum { TM_SQDIFF=0, TM_SQDIFF_NORMED=1, TM_CCORR=2, TM_CCORR_NORMED=3, TM_CCOEFF
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
......
......@@ -69,29 +69,42 @@ namespace cv{
}
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{
......@@ -106,19 +119,23 @@ namespace cv{
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 = &centroidsv.at<double>(l, 0);
centroid[0] = double(integral.x) / row[CC_STAT_AREA];
centroid[1] = double(integral.y) / row[CC_STAT_AREA];
}
}
};
......@@ -196,9 +213,7 @@ namespace cv{
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;
......@@ -347,7 +362,8 @@ namespace cv{
//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);
......@@ -394,13 +410,15 @@ int connectedComponents_sub1(InputArray I, OutputArray L, int connectivity, Stat
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);
......@@ -408,14 +426,16 @@ int connectedComponents(InputArray I, OutputArray L, int connectivity){
}
}
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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment