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
@ -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,
|
CV_EXPORTS_W void matchTemplate( InputArray image, InputArray templ,
|
||||||
OutputArray result, int method );
|
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
|
//! 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
|
//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.
|
//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 connectedComponents(InputArray image, OutputArray labels, int connectivity = 8, int ltype=CV_32S);
|
||||||
CV_EXPORTS_W int connectedComponentsWithStats(InputArray image, OutputArray labels, OutputArray stats, int connectivity = 8);
|
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
|
//! mode of the contour retrieval algorithm
|
||||||
|
@ -69,29 +69,42 @@ namespace cv{
|
|||||||
}
|
}
|
||||||
void finish(){}
|
void finish(){}
|
||||||
};
|
};
|
||||||
|
struct Point2ui64{
|
||||||
|
uint64_t x, y;
|
||||||
|
Point2ui64(uint64_t _x, uint64_t _y):x(_x), y(_y){}
|
||||||
|
};
|
||||||
template<typename LabelT>
|
template<typename LabelT>
|
||||||
struct CCStatsOp{
|
struct CCStatsOp{
|
||||||
|
OutputArray _mstatsv;
|
||||||
cv::Mat statsv;
|
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
|
inline
|
||||||
void init(const LabelT nlabels){
|
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){
|
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_LEFT] = std::numeric_limits<LabelT>::max();
|
||||||
row[CC_STAT_TOP] = 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_WIDTH] = std::numeric_limits<LabelT>::min();
|
||||||
row[CC_STAT_HEIGHT] = std::numeric_limits<LabelT>::min();
|
row[CC_STAT_HEIGHT] = std::numeric_limits<LabelT>::min();
|
||||||
row[CC_STAT_CX] = 0;
|
//row[CC_STAT_CX] = 0;
|
||||||
row[CC_STAT_CY] = 0;
|
//row[CC_STAT_CY] = 0;
|
||||||
row[CC_STAT_AREA] = 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){
|
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]){
|
if(c > row[CC_STAT_WIDTH]){
|
||||||
row[CC_STAT_WIDTH] = c;
|
row[CC_STAT_WIDTH] = c;
|
||||||
}else{
|
}else{
|
||||||
@ -106,19 +119,23 @@ namespace cv{
|
|||||||
row[CC_STAT_TOP] = r;
|
row[CC_STAT_TOP] = r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
row[CC_STAT_INTEGRAL_X] += c;
|
urow[CC_STAT_AREA]++;
|
||||||
row[CC_STAT_INTEGRAL_Y] += r;
|
Point2ui64 &integral = integrals[l];
|
||||||
row[CC_STAT_AREA]++;
|
integral.x += c;
|
||||||
|
integral.y += r;
|
||||||
}
|
}
|
||||||
void finish(){
|
void finish(){
|
||||||
for(int l = 0; l < statsv.rows; ++l){
|
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_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_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_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_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
|
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>
|
template<typename LabelT, typename PixelT, typename StatsOp = NoOp<LabelT>, int connectivity = 8>
|
||||||
struct LabelingImpl{
|
struct LabelingImpl{
|
||||||
LabelT operator()(InputArray _I, OutputArray _L, StatsOp &sop){
|
LabelT operator()(const cv::Mat &I, cv::Mat &L, StatsOp &sop){
|
||||||
cv::Mat I = _I.getMat();
|
|
||||||
cv::Mat L = _L.getMat();
|
|
||||||
CV_Assert(L.rows == I.rows);
|
CV_Assert(L.rows == I.rows);
|
||||||
CV_Assert(L.cols == I.cols);
|
CV_Assert(L.cols == I.cols);
|
||||||
const int rows = L.rows;
|
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
|
//L's type must have an appropriate depth for the number of pixels in I
|
||||||
template<typename StatsOp>
|
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(L.channels() == 1 && I.channels() == 1);
|
||||||
CV_Assert(connectivity == 8 || connectivity == 4);
|
CV_Assert(connectivity == 8 || connectivity == 4);
|
||||||
|
|
||||||
@ -394,13 +410,15 @@ int connectedComponents_sub1(InputArray I, OutputArray L, int connectivity, Stat
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int connectedComponents(InputArray I, OutputArray L, int connectivity){
|
int connectedComponents(InputArray _I, OutputArray _L, int connectivity, int ltype){
|
||||||
int lDepth = L.depth();
|
const cv::Mat I = _I.getMat();
|
||||||
if(lDepth == CV_8U){
|
_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);
|
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);
|
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);
|
connectedcomponents::NoOp<uint32_t> sop; return connectedComponents_sub1(I, L, connectivity, sop);
|
||||||
}else{
|
}else{
|
||||||
CV_Assert(false);
|
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 connectedComponentsWithStats(InputArray _I, OutputArray _L, OutputArray statsv, OutputArray centroids, int connectivity, int ltype){
|
||||||
int lDepth = L.depth();
|
const cv::Mat I = _I.getMat();
|
||||||
if(lDepth == CV_8U){
|
_L.create(I.size(), CV_MAT_TYPE(ltype));
|
||||||
connectedcomponents::CCStatsOp<uint8_t> sop(statsv); return connectedComponents_sub1(I, L, connectivity, sop);
|
cv::Mat L = _L.getMat();
|
||||||
}else if(lDepth == CV_16U){
|
if(ltype == CV_8U){
|
||||||
connectedcomponents::CCStatsOp<uint16_t> sop(statsv); return connectedComponents_sub1(I, L, connectivity, sop);
|
connectedcomponents::CCStatsOp<uint8_t> sop(statsv, centroids); return connectedComponents_sub1(I, L, connectivity, sop);
|
||||||
}else if(lDepth == CV_32S){
|
}else if(ltype == CV_16U){
|
||||||
connectedcomponents::CCStatsOp<uint32_t> sop(statsv); return connectedComponents_sub1(I, L, connectivity, sop);
|
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{
|
}else{
|
||||||
CV_Assert(false);
|
CV_Assert(false);
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user