use a ltype parameter to determine result Label image type; export stats with differening types over different outputarrays
This commit is contained in:
parent
6a4d881a78
commit
e70b3ef598
modules/imgproc
@ -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 = ¢roidsv.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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user