From 45b4f4f32bf2aec782432c9755e2e5b03a7bd152 Mon Sep 17 00:00:00 2001 From: Jason Newton Date: Fri, 24 Aug 2012 23:57:17 -0700 Subject: [PATCH 01/34] connectedComponents: warning free version --- .../include/opencv2/imgproc/imgproc.hpp | 5 + modules/imgproc/src/connectedcomponents.cpp | 365 ++++++++++++++++++ samples/cpp/connected_components.cpp | 32 +- 3 files changed, 384 insertions(+), 18 deletions(-) create mode 100644 modules/imgproc/src/connectedcomponents.cpp diff --git a/modules/imgproc/include/opencv2/imgproc/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc/imgproc.hpp index 63f521814..3d80cfee4 100644 --- a/modules/imgproc/include/opencv2/imgproc/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc/imgproc.hpp @@ -1091,6 +1091,11 @@ 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 ); +//! 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. +CV_EXPORTS_W uint64_t connectedComponents(Mat &L, const Mat &I, int connectivity = 8); + + //! mode of the contour retrieval algorithm enum { diff --git a/modules/imgproc/src/connectedcomponents.cpp b/modules/imgproc/src/connectedcomponents.cpp new file mode 100644 index 000000000..cc83f9748 --- /dev/null +++ b/modules/imgproc/src/connectedcomponents.cpp @@ -0,0 +1,365 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of Intel Corporation may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +// 2011 Jason Newton +//M*/ +// +#include "precomp.hpp" + +namespace cv{ + namespace connectedcomponents{ + using std::vector; + + //Find the root of the tree of node i + template + inline static + LabelT findRoot(const vector &P, LabelT i){ + LabelT root = i; + while(P[root] < root){ + root = P[root]; + } + return root; + } + + //Make all nodes in the path of node i point to root + template + inline static + void setRoot(vector &P, LabelT i, LabelT root){ + while(P[i] < i){ + LabelT j = P[i]; + P[i] = root; + i = j; + } + P[i] = root; + } + + //Find the root of the tree of the node i and compress the path in the process + template + inline static + LabelT find(vector &P, LabelT i){ + LabelT root = findRoot(P, i); + setRoot(P, i, root); + return root; + } + + //unite the two trees containing nodes i and j and return the new root + template + inline static + LabelT set_union(vector &P, LabelT i, LabelT j){ + LabelT root = findRoot(P, i); + if(i != j){ + LabelT rootj = findRoot(P, j); + if(root > rootj){ + root = rootj; + } + setRoot(P, j, root); + } + setRoot(P, i, root); + return root; + } + + //Flatten the Union Find tree and relabel the components + template + inline static + LabelT flattenL(vector &P){ + LabelT k = 1; + for(size_t i = 1; i < P.size(); ++i){ + if(P[i] < i){ + P[i] = P[P[i]]; + }else{ + P[i] = k; k = k + 1; + } + } + return k; + } + + ////Flatten the Union Find tree - inconsistent labels + //void flatten(int P[], int size){ + // for(int i = 1; i < size; ++i){ + // P[i] = P[P[i]]; + // } + //} + const int G4[2][2] = {{-1, 0}, {0, -1}};//b, d neighborhoods + const int G8[4][2] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}};//a, b, c, d neighborhoods + //Based on "Two Strategies to Speed up Connected Components Algorithms", the SAUF (Scan array union find) variant + //using decision trees + //Kesheng Wu, et al + template + struct LabelingImpl{ + LabelT operator()(Mat &L, const Mat &I){ + const int rows = L.rows; + const int cols = L.cols; + size_t nPixels = size_t(rows) * cols; + vector P; P.push_back(0); + LabelT l = 1; + //scanning phase + for(int r_i = 0; r_i < rows; ++r_i){ + for(int c_i = 0; c_i < cols; ++c_i){ + if(!I.at(r_i, c_i)){ + L.at(r_i, c_i) = 0; + continue; + } + if(connectivity == 8){ + const int a = 0; + const int b = 1; + const int c = 2; + const int d = 3; + + bool T[4]; + + for(size_t i = 0; i < 4; ++i){ + int gr = r_i + G8[i][0]; + int gc = c_i + G8[i][1]; + T[i] = false; + if(gr >= 0 && gr < rows && gc >= 0 && gc < cols){ + if(I.at(gr, gc)){ + T[i] = true; + } + } + } + + //decision tree + if(T[b]){ + //copy(b) + L.at(r_i, c_i) = L.at(r_i + G8[b][0], c_i + G8[b][1]); + }else{//not b + if(T[c]){ + if(T[a]){ + //copy(c, a) + L.at(r_i, c_i) = set_union(P, L.at(r_i + G8[c][0], c_i + G8[c][1]), L.at(r_i + G8[a][0], c_i + G8[a][1])); + }else{ + if(T[d]){ + //copy(c, d) + L.at(r_i, c_i) = set_union(P, L.at(r_i + G8[c][0], c_i + G8[c][1]), L.at(r_i + G8[d][0], c_i + G8[d][1])); + }else{ + //copy(c) + L.at(r_i, c_i) = L.at(r_i + G8[c][0], c_i + G8[c][1]); + } + } + }else{//not c + if(T[a]){ + //copy(a) + L.at(r_i, c_i) = L.at(r_i + G8[a][0], c_i + G8[a][1]); + }else{ + if(T[d]){ + //copy(d) + L.at(r_i, c_i) = L.at(r_i + G8[d][0], c_i + G8[d][1]); + }else{ + //new label + L.at(r_i, c_i) = l; + P.push_back(l);//P[l] = l; + l = l + 1; + } + } + } + } + }else{ + //B & D only + const int b = 0; + const int d = 1; + assert(connectivity == 4); + bool T[2]; + for(size_t i = 0; i < 2; ++i){ + int gr = r_i + G4[i][0]; + int gc = c_i + G4[i][1]; + T[i] = false; + if(gr >= 0 && gr < rows && gc >= 0 && gc < cols){ + if(I.at(gr, gc)){ + T[i] = true; + } + } + } + + if(T[b]){ + if(T[d]){ + //copy(d, b) + L.at(r_i, c_i) = set_union(P, L.at(r_i + G4[d][0], c_i + G4[d][1]), L.at(r_i + G4[b][0], c_i + G4[b][1])); + }else{ + //copy(b) + L.at(r_i, c_i) = L.at(r_i + G4[b][0], c_i + G4[b][1]); + } + }else{ + if(T[d]){ + //copy(d) + L.at(r_i, c_i) = L.at(r_i + G4[d][0], c_i + G4[d][1]); + }else{ + //new label + L.at(r_i, c_i) = l; + P.push_back(l);//P[l] = l; + l = l + 1; + } + } + + } + } + } + + //analysis + LabelT nLabels = flattenL(P); + + //assign final labels + for(size_t r = 0; r < rows; ++r){ + for(size_t c = 0; c < cols; ++c){ + L.at(r, c) = P[L.at(r, c)]; + } + } + + return nLabels; + }//End function LabelingImpl operator() + + };//End struct LabelingImpl +}//end namespace connectedcomponents + +//L's type must have an appropriate depth for the number of pixels in I +uint64_t connectedComponents(Mat &L, const Mat &I, int connectivity){ + CV_Assert(L.rows == I.rows); + CV_Assert(L.cols == I.cols); + CV_Assert(L.channels() == 1 && I.channels() == 1); + CV_Assert(connectivity == 8 || connectivity == 4); + + int lDepth = L.depth(); + int iDepth = I.depth(); + using connectedcomponents::LabelingImpl; + //warn if L's depth is not sufficient? + + if(lDepth == CV_8U){ + if(iDepth == CV_8U || iDepth == CV_8S){ + if(connectivity == 4){ + return (uint64_t) LabelingImpl()(L, I); + }else{ + return (uint64_t) LabelingImpl()(L, I); + } + }else if(iDepth == CV_16U || iDepth == CV_16S){ + if(connectivity == 4){ + return (uint64_t) LabelingImpl()(L, I); + }else{ + return (uint64_t) LabelingImpl()(L, I); + } + }else if(iDepth == CV_32S){ + if(connectivity == 4){ + return (uint64_t) LabelingImpl()(L, I); + }else{ + return (uint64_t) LabelingImpl()(L, I); + } + }else if(iDepth == CV_32F){ + if(connectivity == 4){ + return (uint64_t) LabelingImpl()(L, I); + }else{ + return (uint64_t) LabelingImpl()(L, I); + } + }else if(iDepth == CV_64F){ + if(connectivity == 4){ + return (uint64_t) LabelingImpl()(L, I); + }else{ + return (uint64_t) LabelingImpl()(L, I); + } + } + }else if(lDepth == CV_16U){ + if(iDepth == CV_8U || iDepth == CV_8S){ + if(connectivity == 4){ + return (uint64_t) LabelingImpl()(L, I); + }else{ + return (uint64_t) LabelingImpl()(L, I); + } + }else if(iDepth == CV_16U || iDepth == CV_16S){ + if(connectivity == 4){ + return (uint64_t) LabelingImpl()(L, I); + }else{ + return (uint64_t) LabelingImpl()(L, I); + } + }else if(iDepth == CV_32S){ + if(connectivity == 4){ + return (uint64_t) LabelingImpl()(L, I); + }else{ + return (uint64_t) LabelingImpl()(L, I); + } + }else if(iDepth == CV_32F){ + if(connectivity == 4){ + return (uint64_t) LabelingImpl()(L, I); + }else{ + return (uint64_t) LabelingImpl()(L, I); + } + }else if(iDepth == CV_64F){ + if(connectivity == 4){ + return (uint64_t) LabelingImpl()(L, I); + }else{ + return (uint64_t) LabelingImpl()(L, I); + } + } + }else if(lDepth == CV_32S){ + if(iDepth == CV_8U || iDepth == CV_8S){ + if(connectivity == 4){ + return (uint64_t) LabelingImpl()(L, I); + }else{ + return (uint64_t) LabelingImpl()(L, I); + } + }else if(iDepth == CV_16U || iDepth == CV_16S){ + if(connectivity == 4){ + return (uint64_t) LabelingImpl()(L, I); + }else{ + return (uint64_t) LabelingImpl()(L, I); + } + }else if(iDepth == CV_32S){ + if(connectivity == 4){ + return (uint64_t) LabelingImpl()(L, I); + }else{ + return (uint64_t) LabelingImpl()(L, I); + } + }else if(iDepth == CV_32F){ + if(connectivity == 4){ + return (uint64_t) LabelingImpl()(L, I); + }else{ + return (uint64_t) LabelingImpl()(L, I); + } + }else if(iDepth == CV_64F){ + if(connectivity == 4){ + return (uint64_t) LabelingImpl()(L, I); + }else{ + return (uint64_t) LabelingImpl()(L, I); + } + } + } + + CV_Error(CV_StsUnsupportedFormat, "unsupported label/image type"); + return -1; +} + + +} + diff --git a/samples/cpp/connected_components.cpp b/samples/cpp/connected_components.cpp index c915bcda4..6d3357fb6 100644 --- a/samples/cpp/connected_components.cpp +++ b/samples/cpp/connected_components.cpp @@ -11,25 +11,21 @@ int threshval = 100; static void on_trackbar(int, void*) { Mat bw = threshval < 128 ? (img < threshval) : (img > threshval); - - vector > contours; - vector hierarchy; - - findContours( bw, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE ); - - Mat dst = Mat::zeros(img.size(), CV_8UC3); - - if( !contours.empty() && !hierarchy.empty() ) - { - // iterate through all the top-level contours, - // draw each connected component with its own random color - int idx = 0; - for( ; idx >= 0; idx = hierarchy[idx][0] ) - { - Scalar color( (rand()&255), (rand()&255), (rand()&255) ); - drawContours( dst, contours, idx, color, CV_FILLED, 8, hierarchy ); - } + Mat labelImage(img.size(), CV_32S); + int nLabels = connectedComponents(labelImage, bw, 8); + Vec3b colors[nLabels]; + colors[0] = Vec3b(0, 0, 0);//background + for(int label = 1; label < nLabels; ++label){ + colors[label] = Vec3b( (rand()&255), (rand()&255), (rand()&255) ); } + Mat dst(img.size(), CV_8UC3); + for(int r = 0; r < dst.rows; ++r){ + for(int c = 0; c < dst.cols; ++c){ + int label = labelImage.at(r, c); + Vec3b &pixel = dst.at(r, c); + pixel = colors[label]; + } + } imshow( "Connected Components", dst ); } From 4c0cb2576d588b641b3496628eb2c07cfeedb7b6 Mon Sep 17 00:00:00 2001 From: Jason Newton Date: Sat, 25 Aug 2012 02:31:52 -0700 Subject: [PATCH 02/34] connectedComponents: peep-hole optimizations, mostly surrouding the fact that cv::Mat::at is expensive in a tight-loop -also added a "blobstats" version --- .../include/opencv2/imgproc/imgproc.hpp | 17 +- modules/imgproc/src/connectedcomponents.cpp | 354 ++++++++++++------ samples/cpp/connected_components.cpp | 2 +- 3 files changed, 252 insertions(+), 121 deletions(-) diff --git a/modules/imgproc/include/opencv2/imgproc/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc/imgproc.hpp index 3d80cfee4..0cb761b40 100644 --- a/modules/imgproc/include/opencv2/imgproc/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc/imgproc.hpp @@ -1091,9 +1091,24 @@ 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 ); + +struct CV_EXPORTS ConnectedComponentStats +{ + int32_t lower_x; + int32_t lower_y; + int32_t upper_x; + int32_t upper_y; + double centroid_x; + double centroid_y; + uint64_t integral_x; + uint64_t integral_y; + uint32_t area; +}; //! 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. +//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 uint64_t connectedComponents(Mat &L, const Mat &I, int connectivity = 8); +CV_EXPORTS_W uint64_t connectedComponents(Mat &L, const Mat &I, std::vector &statsv, int connectivity = 8); //! mode of the contour retrieval algorithm diff --git a/modules/imgproc/src/connectedcomponents.cpp b/modules/imgproc/src/connectedcomponents.cpp index cc83f9748..50a1ca1e0 100644 --- a/modules/imgproc/src/connectedcomponents.cpp +++ b/modules/imgproc/src/connectedcomponents.cpp @@ -41,15 +41,81 @@ //M*/ // #include "precomp.hpp" +#include namespace cv{ namespace connectedcomponents{ - using std::vector; + + template + struct NoOp{ + NoOp(){ + } + void init(const LabelT labels){ + (void) labels; + } + inline + void operator()(int r, int c, LabelT l){ + (void) r; + (void) c; + (void) l; + } + void finish(){} + }; + template + struct CCStatsOp{ + std::vector &statsv; + CCStatsOp(std::vector &_statsv): statsv(_statsv){ + } + inline + void init(const LabelT nlabels){ + statsv.clear(); + cv::ConnectedComponentStats stats = cv::ConnectedComponentStats(); + stats.lower_x = std::numeric_limits::max(); + stats.lower_y = std::numeric_limits::max(); + stats.upper_x = std::numeric_limits::min(); + stats.upper_y = std::numeric_limits::min(); + stats.centroid_x = 0; + stats.centroid_y = 0; + stats.integral_x = 0; + stats.integral_y = 0; + stats.area = 0; + statsv.resize(nlabels, stats); + } + void operator()(int r, int c, LabelT l){ + ConnectedComponentStats &stats = statsv[l]; + if(c > stats.upper_x){ + stats.upper_x = c; + }else{ + if(c < stats.lower_x){ + stats.lower_x = c; + } + } + if(r > stats.upper_y){ + stats.upper_y = r; + }else{ + if(r < stats.lower_y){ + stats.lower_y = r; + } + } + stats.integral_x += c; + stats.integral_y += r; + stats.area++; + } + void finish(){ + for(size_t l = 0; l < statsv.size(); ++l){ + ConnectedComponentStats &stats = statsv[l]; + stats.lower_x = std::min(stats.lower_x, stats.upper_x); + stats.lower_y = std::min(stats.lower_y, stats.upper_y); + stats.centroid_x = stats.integral_x / double(stats.area); + stats.centroid_y = stats.integral_y / double(stats.area); + } + } + }; //Find the root of the tree of node i template inline static - LabelT findRoot(const vector &P, LabelT i){ + LabelT findRoot(const LabelT *P, LabelT i){ LabelT root = i; while(P[root] < root){ root = P[root]; @@ -60,7 +126,7 @@ namespace cv{ //Make all nodes in the path of node i point to root template inline static - void setRoot(vector &P, LabelT i, LabelT root){ + void setRoot(LabelT *P, LabelT i, LabelT root){ while(P[i] < i){ LabelT j = P[i]; P[i] = root; @@ -72,7 +138,7 @@ namespace cv{ //Find the root of the tree of the node i and compress the path in the process template inline static - LabelT find(vector &P, LabelT i){ + LabelT find(LabelT *P, LabelT i){ LabelT root = findRoot(P, i); setRoot(P, i, root); return root; @@ -81,7 +147,7 @@ namespace cv{ //unite the two trees containing nodes i and j and return the new root template inline static - LabelT set_union(vector &P, LabelT i, LabelT j){ + LabelT set_union(LabelT *P, LabelT i, LabelT j){ LabelT root = findRoot(P, i); if(i != j){ LabelT rootj = findRoot(P, j); @@ -97,9 +163,9 @@ namespace cv{ //Flatten the Union Find tree and relabel the components template inline static - LabelT flattenL(vector &P){ + LabelT flattenL(LabelT *P, LabelT length){ LabelT k = 1; - for(size_t i = 1; i < P.size(); ++i){ + for(LabelT i = 1; i < length; ++i){ if(P[i] < i){ P[i] = P[P[i]]; }else{ @@ -109,137 +175,155 @@ namespace cv{ return k; } - ////Flatten the Union Find tree - inconsistent labels - //void flatten(int P[], int size){ - // for(int i = 1; i < size; ++i){ - // P[i] = P[P[i]]; - // } - //} - const int G4[2][2] = {{-1, 0}, {0, -1}};//b, d neighborhoods - const int G8[4][2] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}};//a, b, c, d neighborhoods //Based on "Two Strategies to Speed up Connected Components Algorithms", the SAUF (Scan array union find) variant //using decision trees //Kesheng Wu, et al - template + //Note: rows are encoded as position in the "rows" array to save lookup times + //reference for 4-way: {{-1, 0}, {0, -1}};//b, d neighborhoods + const int G4[2][2] = {{1, 0}, {0, -1}};//b, d neighborhoods + //reference for 8-way: {{-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, int connectivity = 8> struct LabelingImpl{ - LabelT operator()(Mat &L, const Mat &I){ + LabelT operator()(Mat &L, const Mat &I, StatsOp &sop){ const int rows = L.rows; const int cols = L.cols; - size_t nPixels = size_t(rows) * cols; - vector P; P.push_back(0); - LabelT l = 1; + size_t Plength = (size_t(rows + 3 - 1)/3) * (size_t(cols + 3 - 1)/3); + if(connectivity == 4){ + Plength = 4 * Plength;//a quick and dirty upper bound, an exact answer exists if you want to find it + //the 4 comes from the fact that a 3x3 block can never have more than 4 unique labels + } + LabelT *P = (LabelT *) fastMalloc(sizeof(LabelT) * Plength); + P[0] = 0; + LabelT lunique = 1; //scanning phase for(int r_i = 0; r_i < rows; ++r_i){ - for(int c_i = 0; c_i < cols; ++c_i){ - if(!I.at(r_i, c_i)){ - L.at(r_i, c_i) = 0; - continue; - } - if(connectivity == 8){ - const int a = 0; - const int b = 1; - const int c = 2; - const int d = 3; - - bool T[4]; - - for(size_t i = 0; i < 4; ++i){ - int gr = r_i + G8[i][0]; - int gc = c_i + G8[i][1]; - T[i] = false; - if(gr >= 0 && gr < rows && gc >= 0 && gc < cols){ - if(I.at(gr, gc)){ - T[i] = true; - } - } + LabelT *Lrow = (LabelT *)(L.data + L.step.p[0] * r_i); + LabelT *Lrow_prev = (LabelT *)(((char *)Lrow) - L.step.p[0]); + const PixelT *Irow = (PixelT *)(I.data + I.step.p[0] * r_i); + const PixelT *Irow_prev = (const PixelT *)(((char *)Irow) - I.step.p[0]); + LabelT *Lrows[2] = { + Lrow, + Lrow_prev + }; + const PixelT *Irows[2] = { + Irow, + Irow_prev + }; + if(connectivity == 8){ + const int a = 0; + const int b = 1; + const int c = 2; + const int d = 3; + const bool T_a_r = (r_i - G8[a][0]) >= 0; + const bool T_b_r = (r_i - G8[b][0]) >= 0; + const bool T_c_r = (r_i - G8[c][0]) >= 0; + for(int c_i = 0; Irows[0] != Irow + cols; ++Irows[0], c_i++){ + if(!*Irows[0]){ + Lrow[c_i] = 0; + continue; } + Irows[1] = Irow_prev + c_i; + Lrows[0] = Lrow + c_i; + Lrows[1] = Lrow_prev + c_i; + const bool T_a = T_a_r && (c_i + G8[a][1]) >= 0 && *(Irows[G8[a][0]] + G8[a][1]); + const bool T_b = T_b_r && *(Irows[G8[b][0]] + G8[b][1]); + const bool T_c = T_c_r && (c_i + G8[c][1]) < cols && *(Irows[G8[c][0]] + G8[c][1]); + const bool T_d = (c_i + G8[d][1]) >= 0 && *(Irows[G8[d][0]] + G8[d][1]); //decision tree - if(T[b]){ + if(T_b){ //copy(b) - L.at(r_i, c_i) = L.at(r_i + G8[b][0], c_i + G8[b][1]); + *Lrows[0] = *(Lrows[G8[b][0]] + G8[b][1]); }else{//not b - if(T[c]){ - if(T[a]){ + if(T_c){ + if(T_a){ //copy(c, a) - L.at(r_i, c_i) = set_union(P, L.at(r_i + G8[c][0], c_i + G8[c][1]), L.at(r_i + G8[a][0], c_i + G8[a][1])); + *Lrows[0] = set_union(P, *(Lrows[G8[c][0]] + G8[c][1]), *(Lrows[G8[a][0]] + G8[a][1])); }else{ - if(T[d]){ + if(T_d){ //copy(c, d) - L.at(r_i, c_i) = set_union(P, L.at(r_i + G8[c][0], c_i + G8[c][1]), L.at(r_i + G8[d][0], c_i + G8[d][1])); + *Lrows[0] = set_union(P, *(Lrows[G8[c][0]] + G8[c][1]), *(Lrows[G8[d][0]] + G8[d][1])); }else{ //copy(c) - L.at(r_i, c_i) = L.at(r_i + G8[c][0], c_i + G8[c][1]); + *Lrows[0] = *(Lrows[G8[c][0]] + G8[c][1]); } } }else{//not c - if(T[a]){ + if(T_a){ //copy(a) - L.at(r_i, c_i) = L.at(r_i + G8[a][0], c_i + G8[a][1]); + *Lrows[0] = *(Lrows[G8[a][0]] + G8[a][1]); }else{ - if(T[d]){ + if(T_d){ //copy(d) - L.at(r_i, c_i) = L.at(r_i + G8[d][0], c_i + G8[d][1]); + *Lrows[0] = *(Lrows[G8[d][0]] + G8[d][1]); }else{ //new label - L.at(r_i, c_i) = l; - P.push_back(l);//P[l] = l; - l = l + 1; + *Lrows[0] = lunique; + P[lunique] = lunique; + lunique = lunique + 1; } } } } - }else{ - //B & D only - const int b = 0; - const int d = 1; - assert(connectivity == 4); - bool T[2]; - for(size_t i = 0; i < 2; ++i){ - int gr = r_i + G4[i][0]; - int gc = c_i + G4[i][1]; - T[i] = false; - if(gr >= 0 && gr < rows && gc >= 0 && gc < cols){ - if(I.at(gr, gc)){ - T[i] = true; - } - } + } + }else{ + //B & D only + assert(connectivity == 4); + const int b = 0; + const int d = 1; + const bool T_b_r = (r_i - G4[b][0]) >= 0; + for(int c_i = 0; Irows[0] != Irow + cols; ++Irows[0], c_i++){ + if(!*Irows[0]){ + Lrow[c_i] = 0; + continue; } - - if(T[b]){ - if(T[d]){ + Irows[1] = Irow_prev + c_i; + Lrows[0] = Lrow + c_i; + Lrows[1] = Lrow_prev + c_i; + const bool T_b = T_b_r && *(Irows[G4[b][0]] + G4[b][1]); + const bool T_d = (c_i + G4[d][1]) >= 0 && *(Irows[G4[d][0]] + G4[d][1]); + if(T_b){ + if(T_d){ //copy(d, b) - L.at(r_i, c_i) = set_union(P, L.at(r_i + G4[d][0], c_i + G4[d][1]), L.at(r_i + G4[b][0], c_i + G4[b][1])); + *Lrows[0] = set_union(P, *(Lrows[G4[d][0]] + G4[d][1]), *(Lrows[G4[b][0]] + G4[b][1])); }else{ //copy(b) - L.at(r_i, c_i) = L.at(r_i + G4[b][0], c_i + G4[b][1]); + *Lrows[0] = *(Lrows[G4[b][0]] + G4[b][1]); } }else{ - if(T[d]){ + if(T_d){ //copy(d) - L.at(r_i, c_i) = L.at(r_i + G4[d][0], c_i + G4[d][1]); + *Lrows[0] = *(Lrows[G4[d][0]] + G4[d][1]); }else{ //new label - L.at(r_i, c_i) = l; - P.push_back(l);//P[l] = l; - l = l + 1; + *Lrows[0] = lunique; + P[lunique] = lunique; + lunique = lunique + 1; } } - } } } //analysis - LabelT nLabels = flattenL(P); + LabelT nLabels = flattenL(P, lunique); + sop.init(nLabels); - //assign final labels - for(size_t r = 0; r < rows; ++r){ - for(size_t c = 0; c < cols; ++c){ - L.at(r, c) = P[L.at(r, c)]; + for(int r_i = 0; r_i < rows; ++r_i){ + LabelT *Lrow_start = (LabelT *)(L.data + L.step.p[0] * r_i); + LabelT *Lrow_end = Lrow_start + cols; + LabelT *Lrow = Lrow_start; + for(int c_i = 0; Lrow != Lrow_end; ++Lrow, ++c_i){ + const LabelT l = P[*Lrow]; + *Lrow = l; + sop(r_i, c_i, l); } } + sop.finish(); + fastFree(P); + return nLabels; }//End function LabelingImpl operator() @@ -247,7 +331,8 @@ namespace cv{ }//end namespace connectedcomponents //L's type must have an appropriate depth for the number of pixels in I -uint64_t connectedComponents(Mat &L, const Mat &I, int connectivity){ +template +uint64_t connectedComponents_sub1(Mat &L, const Mat &I, int connectivity, StatsOp &sop){ CV_Assert(L.rows == I.rows); CV_Assert(L.cols == I.cols); CV_Assert(L.channels() == 1 && I.channels() == 1); @@ -261,98 +346,102 @@ uint64_t connectedComponents(Mat &L, const Mat &I, int connectivity){ if(lDepth == CV_8U){ if(iDepth == CV_8U || iDepth == CV_8S){ if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); }else{ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); } }else if(iDepth == CV_16U || iDepth == CV_16S){ if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); }else{ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); } }else if(iDepth == CV_32S){ if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); }else{ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); } }else if(iDepth == CV_32F){ if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); }else{ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); } }else if(iDepth == CV_64F){ if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); }else{ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); } } }else if(lDepth == CV_16U){ if(iDepth == CV_8U || iDepth == CV_8S){ if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); }else{ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); } }else if(iDepth == CV_16U || iDepth == CV_16S){ if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); }else{ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); } }else if(iDepth == CV_32S){ if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); }else{ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); } }else if(iDepth == CV_32F){ if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); }else{ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); } }else if(iDepth == CV_64F){ if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); }else{ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); } } }else if(lDepth == CV_32S){ + //note that signed types don't really make sense here and not being able to use uint32_t matters for scientific projects + //OpenCV: how should we proceed? .at typechecks in debug mode if(iDepth == CV_8U || iDepth == CV_8S){ if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); }else{ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); } }else if(iDepth == CV_16U || iDepth == CV_16S){ if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); }else{ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); } }else if(iDepth == CV_32S){ if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); }else{ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); } }else if(iDepth == CV_32F){ if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); }else{ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); } }else if(iDepth == CV_64F){ if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); }else{ - return (uint64_t) LabelingImpl()(L, I); + return (uint64_t) LabelingImpl()(L, I, sop); } + }else{ + CV_Assert(false); } } @@ -360,6 +449,33 @@ uint64_t connectedComponents(Mat &L, const Mat &I, int connectivity){ return -1; } +uint64_t connectedComponents(Mat &L, const Mat &I, int connectivity){ + int lDepth = L.depth(); + if(lDepth == CV_8U){ + connectedcomponents::NoOp sop; return connectedComponents_sub1(L, I, connectivity, sop); + }else if(lDepth == CV_16U){ + connectedcomponents::NoOp sop; return connectedComponents_sub1(L, I, connectivity, sop); + }else if(lDepth == CV_32S){ + connectedcomponents::NoOp sop; return connectedComponents_sub1(L, I, connectivity, sop); + }else{ + CV_Assert(false); + return 0; + } +} + +uint64_t connectedComponents(Mat &L, const Mat &I, std::vector &statsv, int connectivity){ + int lDepth = L.depth(); + if(lDepth == CV_8U){ + connectedcomponents::CCStatsOp sop(statsv); return connectedComponents_sub1(L, I, connectivity, sop); + }else if(lDepth == CV_16U){ + connectedcomponents::CCStatsOp sop(statsv); return connectedComponents_sub1(L, I, connectivity, sop); + }else if(lDepth == CV_32S){ + connectedcomponents::CCStatsOp sop(statsv); return connectedComponents_sub1(L, I, connectivity, sop); + }else{ + CV_Assert(false); + return 0; + } +} } diff --git a/samples/cpp/connected_components.cpp b/samples/cpp/connected_components.cpp index 6d3357fb6..7b362dfd6 100644 --- a/samples/cpp/connected_components.cpp +++ b/samples/cpp/connected_components.cpp @@ -12,7 +12,7 @@ static void on_trackbar(int, void*) { Mat bw = threshval < 128 ? (img < threshval) : (img > threshval); Mat labelImage(img.size(), CV_32S); - int nLabels = connectedComponents(labelImage, bw, 8); + uint64_t nLabels = connectedComponents(labelImage, bw, 8); Vec3b colors[nLabels]; colors[0] = Vec3b(0, 0, 0);//background for(int label = 1; label < nLabels; ++label){ From 85880397c411b58b665a877b2eef5b1dd0cb1863 Mon Sep 17 00:00:00 2001 From: Jason Newton Date: Mon, 5 Nov 2012 12:02:53 -0800 Subject: [PATCH 03/34] connectedcomponents: use opencv integral types, add to docs, fix up things for a python export --- ...uctural_analysis_and_shape_descriptors.rst | 42 +++++++++++++++++++ .../include/opencv2/imgproc/imgproc.hpp | 24 +++++------ modules/imgproc/src/connectedcomponents.cpp | 12 +++++- modules/python/src2/cv2.cpp | 12 +++++- 4 files changed, 75 insertions(+), 15 deletions(-) diff --git a/modules/imgproc/doc/structural_analysis_and_shape_descriptors.rst b/modules/imgproc/doc/structural_analysis_and_shape_descriptors.rst index 55cea58d5..ad5c22cbb 100644 --- a/modules/imgproc/doc/structural_analysis_and_shape_descriptors.rst +++ b/modules/imgproc/doc/structural_analysis_and_shape_descriptors.rst @@ -118,6 +118,48 @@ These values are proved to be invariants to the image scale, rotation, and refle .. seealso:: :ocv:func:`matchShapes` +connectedComponents +----------- +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. + +.. ocv:function:: uint64 connectedComponents(Mat &L, const Mat &I, int connectivity = 8) + +.. ocv:function:: uint64 connectedComponentsWithStats(Mat &L, const Mat &I, std::vector &statsv, int connectivity = 8) + + :param L: destitination Labeled image + + :param I: the image to be labeled + + :param connectivity: 8 or 4 for 8-way or 4-way connectivity respectively + + :param statsv: statistics for each label, including the background label + +Statistics information such as bounding box, area, and centroid is exported via the ``ConnectComponentStats`` structure defined as: :: + + class CV_EXPORTS ConnectedComponentStats + { + public: + //! lower left corner column + int lower_x; + //! lower left corner row + int lower_y; + //! upper right corner column + int upper_x; + //! upper right corner row + int upper_y; + //! centroid column + double centroid_x; + //! centroid row + double centroid_y; + //! sum of all columns where the image was non-zero + uint64 integral_x; + //! sum of all rows where the image was non-zero + uint64 integral_y; + //! count of all non-zero pixels + unsigned int area; + }; findContours ---------------- diff --git a/modules/imgproc/include/opencv2/imgproc/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc/imgproc.hpp index 0cb761b40..3c9d78710 100644 --- a/modules/imgproc/include/opencv2/imgproc/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc/imgproc.hpp @@ -1091,24 +1091,24 @@ 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 ); - struct CV_EXPORTS ConnectedComponentStats { - int32_t lower_x; - int32_t lower_y; - int32_t upper_x; - int32_t upper_y; - double centroid_x; - double centroid_y; - uint64_t integral_x; - uint64_t integral_y; - uint32_t area; + int lower_x;//!< lower left corner column + int lower_y;//!< lower left corner row + int upper_x;//!< upper right corner column + int upper_y;//!< upper right corner row + double centroid_x;//!< centroid column + double centroid_y;//!< centroid row + uint64 integral_x;//!< sum of all columns where the image was non-zero + uint64 integral_y;//!< sum of all rows where the image was non-zero + unsigned int area;//!< count of all non-zero pixels }; + //! 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 uint64_t connectedComponents(Mat &L, const Mat &I, int connectivity = 8); -CV_EXPORTS_W uint64_t connectedComponents(Mat &L, const Mat &I, std::vector &statsv, int connectivity = 8); +CV_EXPORTS_W uint64 connectedComponents(CV_OUT Mat &L, const Mat &I, int connectivity = 8); +CV_EXPORTS_W uint64 connectedComponentsWithStats(CV_OUT Mat &L, const Mat &I, CV_OUT std::vector &statsv, int connectivity = 8); //! mode of the contour retrieval algorithm diff --git a/modules/imgproc/src/connectedcomponents.cpp b/modules/imgproc/src/connectedcomponents.cpp index 50a1ca1e0..8e75ce7bd 100644 --- a/modules/imgproc/src/connectedcomponents.cpp +++ b/modules/imgproc/src/connectedcomponents.cpp @@ -43,6 +43,16 @@ #include "precomp.hpp" #include +//It's 2012 and we still let compilers get by without defining standard integer types... +typedef schar int8_t; +typedef uchar uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef int int32_t; +typedef unsigned int uint32_t; +typedef int64 int64_t; +typedef uint64 uint64_t; + namespace cv{ namespace connectedcomponents{ @@ -463,7 +473,7 @@ uint64_t connectedComponents(Mat &L, const Mat &I, int connectivity){ } } -uint64_t connectedComponents(Mat &L, const Mat &I, std::vector &statsv, int connectivity){ +uint64_t connectedComponentsWithStats(Mat &L, const Mat &I, std::vector &statsv, int connectivity){ int lDepth = L.depth(); if(lDepth == CV_8U){ connectedcomponents::CCStatsOp sop(statsv); return connectedComponents_sub1(L, I, connectivity, sop); diff --git a/modules/python/src2/cv2.cpp b/modules/python/src2/cv2.cpp index 28cf00eac..5dbbbb440 100644 --- a/modules/python/src2/cv2.cpp +++ b/modules/python/src2/cv2.cpp @@ -123,6 +123,7 @@ typedef Ptr Ptr_FeatureDetector; typedef Ptr Ptr_DescriptorExtractor; typedef Ptr Ptr_Feature2D; typedef Ptr Ptr_DescriptorMatcher; +typedef vector vector_ConnectedComponentStats; typedef SimpleBlobDetector::Params SimpleBlobDetector_Params; @@ -410,7 +411,7 @@ static bool pyopencv_to(PyObject* obj, bool& value, const char* name = " Date: Thu, 22 Nov 2012 21:26:52 -0800 Subject: [PATCH 04/34] adjust output type to return int32... it should at least be unsigned but this breaks python bindings; remove non-8bit input type support, not worth the binary size --- .../include/opencv2/imgproc/imgproc.hpp | 4 +- modules/imgproc/src/connectedcomponents.cpp | 97 +++---------------- 2 files changed, 15 insertions(+), 86 deletions(-) diff --git a/modules/imgproc/include/opencv2/imgproc/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc/imgproc.hpp index 3c9d78710..5e3da2658 100644 --- a/modules/imgproc/include/opencv2/imgproc/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc/imgproc.hpp @@ -1107,8 +1107,8 @@ struct CV_EXPORTS ConnectedComponentStats //! 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 uint64 connectedComponents(CV_OUT Mat &L, const Mat &I, int connectivity = 8); -CV_EXPORTS_W uint64 connectedComponentsWithStats(CV_OUT Mat &L, const Mat &I, CV_OUT std::vector &statsv, int connectivity = 8); +CV_EXPORTS_W int connectedComponents(CV_OUT Mat &L, const Mat &I, int connectivity = 8); +CV_EXPORTS_W int connectedComponentsWithStats(CV_OUT Mat &L, const Mat &I, CV_OUT std::vector &statsv, int connectivity = 8); //! mode of the contour retrieval algorithm diff --git a/modules/imgproc/src/connectedcomponents.cpp b/modules/imgproc/src/connectedcomponents.cpp index 8e75ce7bd..db118f5cc 100644 --- a/modules/imgproc/src/connectedcomponents.cpp +++ b/modules/imgproc/src/connectedcomponents.cpp @@ -50,8 +50,6 @@ typedef short int16_t; typedef unsigned short uint16_t; typedef int int32_t; typedef unsigned int uint32_t; -typedef int64 int64_t; -typedef uint64 uint64_t; namespace cv{ namespace connectedcomponents{ @@ -342,7 +340,7 @@ namespace cv{ //L's type must have an appropriate depth for the number of pixels in I template -uint64_t connectedComponents_sub1(Mat &L, const Mat &I, int connectivity, StatsOp &sop){ +int connectedComponents_sub1(Mat &L, const Mat &I, int connectivity, StatsOp &sop){ CV_Assert(L.rows == I.rows); CV_Assert(L.cols == I.cols); CV_Assert(L.channels() == 1 && I.channels() == 1); @@ -356,99 +354,31 @@ uint64_t connectedComponents_sub1(Mat &L, const Mat &I, int connectivity, StatsO if(lDepth == CV_8U){ if(iDepth == CV_8U || iDepth == CV_8S){ if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I, sop); + return (int) LabelingImpl()(L, I, sop); }else{ - return (uint64_t) LabelingImpl()(L, I, sop); - } - }else if(iDepth == CV_16U || iDepth == CV_16S){ - if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I, sop); - }else{ - return (uint64_t) LabelingImpl()(L, I, sop); - } - }else if(iDepth == CV_32S){ - if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I, sop); - }else{ - return (uint64_t) LabelingImpl()(L, I, sop); - } - }else if(iDepth == CV_32F){ - if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I, sop); - }else{ - return (uint64_t) LabelingImpl()(L, I, sop); - } - }else if(iDepth == CV_64F){ - if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I, sop); - }else{ - return (uint64_t) LabelingImpl()(L, I, sop); + return (int) LabelingImpl()(L, I, sop); } + }else{ + CV_Assert(false); } }else if(lDepth == CV_16U){ if(iDepth == CV_8U || iDepth == CV_8S){ if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I, sop); + return (int) LabelingImpl()(L, I, sop); }else{ - return (uint64_t) LabelingImpl()(L, I, sop); - } - }else if(iDepth == CV_16U || iDepth == CV_16S){ - if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I, sop); - }else{ - return (uint64_t) LabelingImpl()(L, I, sop); - } - }else if(iDepth == CV_32S){ - if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I, sop); - }else{ - return (uint64_t) LabelingImpl()(L, I, sop); - } - }else if(iDepth == CV_32F){ - if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I, sop); - }else{ - return (uint64_t) LabelingImpl()(L, I, sop); - } - }else if(iDepth == CV_64F){ - if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I, sop); - }else{ - return (uint64_t) LabelingImpl()(L, I, sop); + return (int) LabelingImpl()(L, I, sop); } + }else{ + CV_Assert(false); } }else if(lDepth == CV_32S){ //note that signed types don't really make sense here and not being able to use uint32_t matters for scientific projects //OpenCV: how should we proceed? .at typechecks in debug mode if(iDepth == CV_8U || iDepth == CV_8S){ if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I, sop); + return (int) LabelingImpl()(L, I, sop); }else{ - return (uint64_t) LabelingImpl()(L, I, sop); - } - }else if(iDepth == CV_16U || iDepth == CV_16S){ - if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I, sop); - }else{ - return (uint64_t) LabelingImpl()(L, I, sop); - } - }else if(iDepth == CV_32S){ - if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I, sop); - }else{ - return (uint64_t) LabelingImpl()(L, I, sop); - } - }else if(iDepth == CV_32F){ - if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I, sop); - }else{ - return (uint64_t) LabelingImpl()(L, I, sop); - } - }else if(iDepth == CV_64F){ - if(connectivity == 4){ - return (uint64_t) LabelingImpl()(L, I, sop); - }else{ - return (uint64_t) LabelingImpl()(L, I, sop); + return (int) LabelingImpl()(L, I, sop); } }else{ CV_Assert(false); @@ -459,7 +389,7 @@ uint64_t connectedComponents_sub1(Mat &L, const Mat &I, int connectivity, StatsO return -1; } -uint64_t connectedComponents(Mat &L, const Mat &I, int connectivity){ +int connectedComponents(Mat &L, const Mat &I, int connectivity){ int lDepth = L.depth(); if(lDepth == CV_8U){ connectedcomponents::NoOp sop; return connectedComponents_sub1(L, I, connectivity, sop); @@ -473,7 +403,7 @@ uint64_t connectedComponents(Mat &L, const Mat &I, int connectivity){ } } -uint64_t connectedComponentsWithStats(Mat &L, const Mat &I, std::vector &statsv, int connectivity){ +int connectedComponentsWithStats(Mat &L, const Mat &I, std::vector &statsv, int connectivity){ int lDepth = L.depth(); if(lDepth == CV_8U){ connectedcomponents::CCStatsOp sop(statsv); return connectedComponents_sub1(L, I, connectivity, sop); @@ -488,4 +418,3 @@ uint64_t connectedComponentsWithStats(Mat &L, const Mat &I, std::vector Date: Tue, 27 Nov 2012 02:25:52 -0800 Subject: [PATCH 05/34] A few changes to comply with upstream requirements for merge. -Change input/output order from (out Labeled, in Image) -> (in Image, Out Labeled) and convert to Input/OutputArrays in the process. -Adopt OutputArray for statistics export so that the algorithm is "wrapper friendly" and not requiring a new struct in language bindings at the expense of using doubles for everything and slowing statistics computation down.. --- .../include/opencv2/imgproc/imgproc.hpp | 17 +-- modules/imgproc/src/connectedcomponents.cpp | 105 +++++++++--------- modules/python/src2/cv2.cpp | 1 - samples/cpp/connected_components.cpp | 2 +- 4 files changed, 59 insertions(+), 66 deletions(-) diff --git a/modules/imgproc/include/opencv2/imgproc/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc/imgproc.hpp index 5e3da2658..8920ed2a1 100644 --- a/modules/imgproc/include/opencv2/imgproc/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc/imgproc.hpp @@ -1091,24 +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 ); -struct CV_EXPORTS ConnectedComponentStats -{ - int lower_x;//!< lower left corner column - int lower_y;//!< lower left corner row - int upper_x;//!< upper right corner column - int upper_y;//!< upper right corner row - double centroid_x;//!< centroid column - double centroid_y;//!< centroid row - uint64 integral_x;//!< sum of all columns where the image was non-zero - uint64 integral_y;//!< sum of all rows where the image was non-zero - unsigned int area;//!< count of all non-zero pixels -}; +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}; //! 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(CV_OUT Mat &L, const Mat &I, int connectivity = 8); -CV_EXPORTS_W int connectedComponentsWithStats(CV_OUT Mat &L, const Mat &I, CV_OUT std::vector &statsv, int connectivity = 8); +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); //! mode of the contour retrieval algorithm diff --git a/modules/imgproc/src/connectedcomponents.cpp b/modules/imgproc/src/connectedcomponents.cpp index db118f5cc..b52a6c729 100644 --- a/modules/imgproc/src/connectedcomponents.cpp +++ b/modules/imgproc/src/connectedcomponents.cpp @@ -71,51 +71,54 @@ namespace cv{ }; template struct CCStatsOp{ - std::vector &statsv; - CCStatsOp(std::vector &_statsv): statsv(_statsv){ + cv::Mat statsv; + CCStatsOp(OutputArray _statsv): statsv(_statsv.getMat()){ } inline void init(const LabelT nlabels){ - statsv.clear(); - cv::ConnectedComponentStats stats = cv::ConnectedComponentStats(); - stats.lower_x = std::numeric_limits::max(); - stats.lower_y = std::numeric_limits::max(); - stats.upper_x = std::numeric_limits::min(); - stats.upper_y = std::numeric_limits::min(); - stats.centroid_x = 0; - stats.centroid_y = 0; - stats.integral_x = 0; - stats.integral_y = 0; - stats.area = 0; - statsv.resize(nlabels, stats); + statsv = cv::Mat(nlabels, CC_STAT_MAX, cv::DataType::type); + for(int l = 0; l < (int) nlabels; ++l){ + double *row = &statsv.at(l, 0); + row[CC_STAT_LEFT] = std::numeric_limits::max(); + row[CC_STAT_TOP] = std::numeric_limits::max(); + row[CC_STAT_WIDTH] = std::numeric_limits::min(); + row[CC_STAT_HEIGHT] = std::numeric_limits::min(); + 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; + } } void operator()(int r, int c, LabelT l){ - ConnectedComponentStats &stats = statsv[l]; - if(c > stats.upper_x){ - stats.upper_x = c; + double *row = &statsv.at(l, 0); + if(c > row[CC_STAT_WIDTH]){ + row[CC_STAT_WIDTH] = c; }else{ - if(c < stats.lower_x){ - stats.lower_x = c; + if(c < row[CC_STAT_LEFT]){ + row[CC_STAT_LEFT] = c; } } - if(r > stats.upper_y){ - stats.upper_y = r; + if(r > row[CC_STAT_HEIGHT]){ + row[CC_STAT_HEIGHT] = r; }else{ - if(r < stats.lower_y){ - stats.lower_y = r; + if(r < row[CC_STAT_TOP]){ + row[CC_STAT_TOP] = r; } } - stats.integral_x += c; - stats.integral_y += r; - stats.area++; + row[CC_STAT_INTEGRAL_X] += c; + row[CC_STAT_INTEGRAL_Y] += r; + row[CC_STAT_AREA]++; } void finish(){ - for(size_t l = 0; l < statsv.size(); ++l){ - ConnectedComponentStats &stats = statsv[l]; - stats.lower_x = std::min(stats.lower_x, stats.upper_x); - stats.lower_y = std::min(stats.lower_y, stats.upper_y); - stats.centroid_x = stats.integral_x / double(stats.area); - stats.centroid_y = stats.integral_y / double(stats.area); + for(int l = 0; l < statsv.rows; ++l){ + double *row = &statsv.at(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]); } } }; @@ -193,7 +196,11 @@ namespace cv{ const int G8[4][2] = {{1, -1}, {1, 0}, {1, 1}, {0, -1}};//a, b, c, d neighborhoods template, int connectivity = 8> struct LabelingImpl{ - LabelT operator()(Mat &L, const Mat &I, StatsOp &sop){ + LabelT operator()(InputArray _I, OutputArray _L, StatsOp &sop){ + cv::Mat I = _I.getMat(); + cv::Mat L = _L.getMat(); + CV_Assert(L.rows == I.rows); + CV_Assert(L.cols == I.cols); const int rows = L.rows; const int cols = L.cols; size_t Plength = (size_t(rows + 3 - 1)/3) * (size_t(cols + 3 - 1)/3); @@ -340,9 +347,7 @@ namespace cv{ //L's type must have an appropriate depth for the number of pixels in I template -int connectedComponents_sub1(Mat &L, const Mat &I, int connectivity, StatsOp &sop){ - CV_Assert(L.rows == I.rows); - CV_Assert(L.cols == I.cols); +int connectedComponents_sub1(InputArray I, OutputArray L, int connectivity, StatsOp &sop){ CV_Assert(L.channels() == 1 && I.channels() == 1); CV_Assert(connectivity == 8 || connectivity == 4); @@ -354,9 +359,9 @@ int connectedComponents_sub1(Mat &L, const Mat &I, int connectivity, StatsOp &so if(lDepth == CV_8U){ if(iDepth == CV_8U || iDepth == CV_8S){ if(connectivity == 4){ - return (int) LabelingImpl()(L, I, sop); + return (int) LabelingImpl()(I, L, sop); }else{ - return (int) LabelingImpl()(L, I, sop); + return (int) LabelingImpl()(I, L, sop); } }else{ CV_Assert(false); @@ -364,9 +369,9 @@ int connectedComponents_sub1(Mat &L, const Mat &I, int connectivity, StatsOp &so }else if(lDepth == CV_16U){ if(iDepth == CV_8U || iDepth == CV_8S){ if(connectivity == 4){ - return (int) LabelingImpl()(L, I, sop); + return (int) LabelingImpl()(I, L, sop); }else{ - return (int) LabelingImpl()(L, I, sop); + return (int) LabelingImpl()(I, L, sop); } }else{ CV_Assert(false); @@ -376,9 +381,9 @@ int connectedComponents_sub1(Mat &L, const Mat &I, int connectivity, StatsOp &so //OpenCV: how should we proceed? .at typechecks in debug mode if(iDepth == CV_8U || iDepth == CV_8S){ if(connectivity == 4){ - return (int) LabelingImpl()(L, I, sop); + return (int) LabelingImpl()(I, L, sop); }else{ - return (int) LabelingImpl()(L, I, sop); + return (int) LabelingImpl()(I, L, sop); } }else{ CV_Assert(false); @@ -389,28 +394,28 @@ int connectedComponents_sub1(Mat &L, const Mat &I, int connectivity, StatsOp &so return -1; } -int connectedComponents(Mat &L, const Mat &I, int connectivity){ +int connectedComponents(InputArray I, OutputArray L, int connectivity){ int lDepth = L.depth(); if(lDepth == CV_8U){ - connectedcomponents::NoOp sop; return connectedComponents_sub1(L, I, connectivity, sop); + connectedcomponents::NoOp sop; return connectedComponents_sub1(I, L, connectivity, sop); }else if(lDepth == CV_16U){ - connectedcomponents::NoOp sop; return connectedComponents_sub1(L, I, connectivity, sop); + connectedcomponents::NoOp sop; return connectedComponents_sub1(I, L, connectivity, sop); }else if(lDepth == CV_32S){ - connectedcomponents::NoOp sop; return connectedComponents_sub1(L, I, connectivity, sop); + connectedcomponents::NoOp sop; return connectedComponents_sub1(I, L, connectivity, sop); }else{ CV_Assert(false); return 0; } } -int connectedComponentsWithStats(Mat &L, const Mat &I, std::vector &statsv, int connectivity){ +int connectedComponentsWithStats(InputArray I, OutputArray L, OutputArray statsv, int connectivity){ int lDepth = L.depth(); if(lDepth == CV_8U){ - connectedcomponents::CCStatsOp sop(statsv); return connectedComponents_sub1(L, I, connectivity, sop); + connectedcomponents::CCStatsOp sop(statsv); return connectedComponents_sub1(I, L, connectivity, sop); }else if(lDepth == CV_16U){ - connectedcomponents::CCStatsOp sop(statsv); return connectedComponents_sub1(L, I, connectivity, sop); + connectedcomponents::CCStatsOp sop(statsv); return connectedComponents_sub1(I, L, connectivity, sop); }else if(lDepth == CV_32S){ - connectedcomponents::CCStatsOp sop(statsv); return connectedComponents_sub1(L, I, connectivity, sop); + connectedcomponents::CCStatsOp sop(statsv); return connectedComponents_sub1(I, L, connectivity, sop); }else{ CV_Assert(false); return 0; diff --git a/modules/python/src2/cv2.cpp b/modules/python/src2/cv2.cpp index 5dbbbb440..bc52f308c 100644 --- a/modules/python/src2/cv2.cpp +++ b/modules/python/src2/cv2.cpp @@ -123,7 +123,6 @@ typedef Ptr Ptr_FeatureDetector; typedef Ptr Ptr_DescriptorExtractor; typedef Ptr Ptr_Feature2D; typedef Ptr Ptr_DescriptorMatcher; -typedef vector vector_ConnectedComponentStats; typedef SimpleBlobDetector::Params SimpleBlobDetector_Params; diff --git a/samples/cpp/connected_components.cpp b/samples/cpp/connected_components.cpp index 7b362dfd6..781ffec04 100644 --- a/samples/cpp/connected_components.cpp +++ b/samples/cpp/connected_components.cpp @@ -12,7 +12,7 @@ static void on_trackbar(int, void*) { Mat bw = threshval < 128 ? (img < threshval) : (img > threshval); Mat labelImage(img.size(), CV_32S); - uint64_t nLabels = connectedComponents(labelImage, bw, 8); + int nLabels = connectedComponents(bw, labelImage, 8); Vec3b colors[nLabels]; colors[0] = Vec3b(0, 0, 0);//background for(int label = 1; label < nLabels; ++label){ From 6a4d881a78f88f6f068d9fd179f054611add2ad7 Mon Sep 17 00:00:00 2001 From: Jason Newton Date: Sat, 8 Dec 2012 21:57:49 -0800 Subject: [PATCH 06/34] use vector instead of non-standard stack allocation. also correct program argument borkage --- samples/cpp/connected_components.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/cpp/connected_components.cpp b/samples/cpp/connected_components.cpp index 781ffec04..617752b42 100644 --- a/samples/cpp/connected_components.cpp +++ b/samples/cpp/connected_components.cpp @@ -13,7 +13,7 @@ static void on_trackbar(int, void*) Mat bw = threshval < 128 ? (img < threshval) : (img > threshval); Mat labelImage(img.size(), CV_32S); int nLabels = connectedComponents(bw, labelImage, 8); - Vec3b colors[nLabels]; + std::vector colors(nLabels); colors[0] = Vec3b(0, 0, 0);//background for(int label = 1; label < nLabels; ++label){ colors[label] = Vec3b( (rand()&255), (rand()&255), (rand()&255) ); @@ -41,14 +41,14 @@ static void help() const char* keys = { - "{@image |stuff.jpg|image for converting to a grayscale}" + "{@image|stuff.jpg|image for converting to a grayscale}" }; int main( int argc, const char** argv ) { help(); CommandLineParser parser(argc, argv, keys); - string inputImage = parser.get(1); + string inputImage = parser.get("@image"); img = imread(inputImage.c_str(), 0); if(img.empty()) From e70b3ef598870739db85cfad4a420c89a6097968 Mon Sep 17 00:00:00 2001 From: Jason Newton Date: Thu, 29 Nov 2012 02:21:06 -0800 Subject: [PATCH 07/34] use a ltype parameter to determine result Label image type; export stats with differening types over different outputarrays --- .../include/opencv2/imgproc/imgproc.hpp | 6 +- modules/imgproc/src/connectedcomponents.cpp | 82 ++++++++++++------- 2 files changed, 54 insertions(+), 34 deletions(-) diff --git a/modules/imgproc/include/opencv2/imgproc/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc/imgproc.hpp index 8920ed2a1..3c682452b 100644 --- a/modules/imgproc/include/opencv2/imgproc/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc/imgproc.hpp @@ -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 diff --git a/modules/imgproc/src/connectedcomponents.cpp b/modules/imgproc/src/connectedcomponents.cpp index b52a6c729..6418337c5 100644 --- a/modules/imgproc/src/connectedcomponents.cpp +++ b/modules/imgproc/src/connectedcomponents.cpp @@ -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 struct CCStatsOp{ + OutputArray _mstatsv; cv::Mat statsv; - CCStatsOp(OutputArray _statsv): statsv(_statsv.getMat()){ + OutputArray _mcentroidsv; + cv::Mat centroidsv; + std::vector 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::type); + _mstatsv.create(cv::Size(nlabels, CC_STAT_MAX), cv::DataType::type); + statsv = _mstatsv.getMat(); + _mcentroidsv.create(cv::Size(nlabels, 2), cv::DataType::type); + centroidsv = _mcentroidsv.getMat(); + for(int l = 0; l < (int) nlabels; ++l){ - double *row = &statsv.at(l, 0); + unsigned int *row = (unsigned int *) &statsv.at(l, 0); row[CC_STAT_LEFT] = std::numeric_limits::max(); row[CC_STAT_TOP] = std::numeric_limits::max(); row[CC_STAT_WIDTH] = std::numeric_limits::min(); row[CC_STAT_HEIGHT] = std::numeric_limits::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(l, 0); + int *row = &statsv.at(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(l, 0); + unsigned int *row = (unsigned int *) &statsv.at(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(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, 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 -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 sop; return connectedComponents_sub1(I, L, connectivity, sop); - }else if(lDepth == CV_16U){ + }else if(ltype == CV_16U){ connectedcomponents::NoOp sop; return connectedComponents_sub1(I, L, connectivity, sop); - }else if(lDepth == CV_32S){ + }else if(ltype == CV_32S){ connectedcomponents::NoOp 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 sop(statsv); return connectedComponents_sub1(I, L, connectivity, sop); - }else if(lDepth == CV_16U){ - connectedcomponents::CCStatsOp sop(statsv); return connectedComponents_sub1(I, L, connectivity, sop); - }else if(lDepth == CV_32S){ - connectedcomponents::CCStatsOp 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 sop(statsv, centroids); return connectedComponents_sub1(I, L, connectivity, sop); + }else if(ltype == CV_16U){ + connectedcomponents::CCStatsOp sop(statsv, centroids); return connectedComponents_sub1(I, L, connectivity, sop); + }else if(ltype == CV_32S){ + connectedcomponents::CCStatsOp sop(statsv, centroids); return connectedComponents_sub1(I, L, connectivity, sop); }else{ CV_Assert(false); return 0; From d094e4bdbe04340f80b95c8e1f281576fdcb4a1f Mon Sep 17 00:00:00 2001 From: Jason Newton Date: Sat, 8 Dec 2012 22:06:15 -0800 Subject: [PATCH 08/34] drop support for 8bit output for size cost relative to utility --- modules/imgproc/src/connectedcomponents.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/modules/imgproc/src/connectedcomponents.cpp b/modules/imgproc/src/connectedcomponents.cpp index 6418337c5..dd1665f65 100644 --- a/modules/imgproc/src/connectedcomponents.cpp +++ b/modules/imgproc/src/connectedcomponents.cpp @@ -414,9 +414,7 @@ int connectedComponents(InputArray _I, OutputArray _L, int connectivity, int lty 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 sop; return connectedComponents_sub1(I, L, connectivity, sop); - }else if(ltype == CV_16U){ + if(ltype == CV_16U){ connectedcomponents::NoOp sop; return connectedComponents_sub1(I, L, connectivity, sop); }else if(ltype == CV_32S){ connectedcomponents::NoOp sop; return connectedComponents_sub1(I, L, connectivity, sop); @@ -430,9 +428,7 @@ int connectedComponentsWithStats(InputArray _I, OutputArray _L, OutputArray stat 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 sop(statsv, centroids); return connectedComponents_sub1(I, L, connectivity, sop); - }else if(ltype == CV_16U){ + if(ltype == CV_16U){ connectedcomponents::CCStatsOp sop(statsv, centroids); return connectedComponents_sub1(I, L, connectivity, sop); }else if(ltype == CV_32S){ connectedcomponents::CCStatsOp sop(statsv, centroids); return connectedComponents_sub1(I, L, connectivity, sop); From 63debf5032df775a52136be92c12e6ef0f5d11a4 Mon Sep 17 00:00:00 2001 From: Jason Newton Date: Mon, 10 Dec 2012 02:21:45 -0800 Subject: [PATCH 09/34] connectedcomponents test case --- .../imgproc/test/test_connectedcomponents.cpp | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 modules/imgproc/test/test_connectedcomponents.cpp diff --git a/modules/imgproc/test/test_connectedcomponents.cpp b/modules/imgproc/test/test_connectedcomponents.cpp new file mode 100644 index 000000000..c428cc074 --- /dev/null +++ b/modules/imgproc/test/test_connectedcomponents.cpp @@ -0,0 +1,108 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#include "test_precomp.hpp" +#include + +using namespace cv; +using namespace std; + +class CV_ConnectedComponentsTest : public cvtest::BaseTest +{ +public: + CV_ConnectedComponentsTest(); + ~CV_ConnectedComponentsTest(); +protected: + void run(int); +}; + +CV_ConnectedComponentsTest::CV_ConnectedComponentsTest() {} +CV_ConnectedComponentsTest::~CV_ConnectedComponentsTest() {} + +void CV_ConnectedComponentsTest::run( int /* start_from */) +{ + string exp_path = string(ts->get_data_path()) + "connectedcomponents/ccomp_exp.png"; + Mat exp = imread(exp_path, 0); + Mat orig = imread(string(ts->get_data_path()) + "connectedcomponents/concentric_circles.png", 0); + + if (orig.empty()) + { + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA ); + return; + } + + Mat bw = orig > 128; + Mat labelImage; + int nLabels = connectedComponents(bw, labelImage, 8, CV_32S); + + for(int r = 0; r < labelImage.rows; ++r){ + for(int c = 0; c < labelImage.cols; ++c){ + int l = labelImage.at(r, c); + bool pass = l >= 0 && l <= nLabels; + if(!pass){ + ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT ); + return; + } + } + } + + if( exp.empty() || orig.size() != exp.size() ) + { + imwrite(exp_path, labelImage); + exp = labelImage; + } + + if (0 != norm(labelImage > 0, exp > 0, NORM_INF)) + { + ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH ); + return; + } + if (nLabels != norm(labelImage, NORM_INF)+1) + { + ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH ); + return; + } + ts->set_failed_test_info(cvtest::TS::OK); +} + +TEST(Imgproc_ConnectedComponents, regression) { CV_ConnectedComponentsTest test; test.safe_run(); } + From 68e77ac051866d0a8745a7e782b35663a6c633b3 Mon Sep 17 00:00:00 2001 From: Jason Newton Date: Sat, 15 Dec 2012 03:36:51 -0800 Subject: [PATCH 10/34] use opencv's integer type convension --- modules/imgproc/src/connectedcomponents.cpp | 34 ++++++++------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/modules/imgproc/src/connectedcomponents.cpp b/modules/imgproc/src/connectedcomponents.cpp index dd1665f65..e0ad06364 100644 --- a/modules/imgproc/src/connectedcomponents.cpp +++ b/modules/imgproc/src/connectedcomponents.cpp @@ -43,14 +43,6 @@ #include "precomp.hpp" #include -//It's 2012 and we still let compilers get by without defining standard integer types... -typedef schar int8_t; -typedef uchar uint8_t; -typedef short int16_t; -typedef unsigned short uint16_t; -typedef int int32_t; -typedef unsigned int uint32_t; - namespace cv{ namespace connectedcomponents{ @@ -70,8 +62,8 @@ namespace cv{ void finish(){} }; struct Point2ui64{ - uint64_t x, y; - Point2ui64(uint64_t _x, uint64_t _y):x(_x), y(_y){} + uint64 x, y; + Point2ui64(uint64 _x, uint64 _y):x(_x), y(_y){} }; template struct CCStatsOp{ @@ -375,9 +367,9 @@ int connectedComponents_sub1(const cv::Mat &I, cv::Mat &L, int connectivity, Sta if(lDepth == CV_8U){ if(iDepth == CV_8U || iDepth == CV_8S){ if(connectivity == 4){ - return (int) LabelingImpl()(I, L, sop); + return (int) LabelingImpl()(I, L, sop); }else{ - return (int) LabelingImpl()(I, L, sop); + return (int) LabelingImpl()(I, L, sop); } }else{ CV_Assert(false); @@ -385,21 +377,21 @@ int connectedComponents_sub1(const cv::Mat &I, cv::Mat &L, int connectivity, Sta }else if(lDepth == CV_16U){ if(iDepth == CV_8U || iDepth == CV_8S){ if(connectivity == 4){ - return (int) LabelingImpl()(I, L, sop); + return (int) LabelingImpl()(I, L, sop); }else{ - return (int) LabelingImpl()(I, L, sop); + return (int) LabelingImpl()(I, L, sop); } }else{ CV_Assert(false); } }else if(lDepth == CV_32S){ - //note that signed types don't really make sense here and not being able to use uint32_t matters for scientific projects + //note that signed types don't really make sense here and not being able to use unsigned matters for scientific projects //OpenCV: how should we proceed? .at typechecks in debug mode if(iDepth == CV_8U || iDepth == CV_8S){ if(connectivity == 4){ - return (int) LabelingImpl()(I, L, sop); + return (int) LabelingImpl()(I, L, sop); }else{ - return (int) LabelingImpl()(I, L, sop); + return (int) LabelingImpl()(I, L, sop); } }else{ CV_Assert(false); @@ -415,9 +407,9 @@ int connectedComponents(InputArray _I, OutputArray _L, int connectivity, int lty _L.create(I.size(), CV_MAT_TYPE(ltype)); cv::Mat L = _L.getMat(); if(ltype == CV_16U){ - connectedcomponents::NoOp sop; return connectedComponents_sub1(I, L, connectivity, sop); + connectedcomponents::NoOp sop; return connectedComponents_sub1(I, L, connectivity, sop); }else if(ltype == CV_32S){ - connectedcomponents::NoOp sop; return connectedComponents_sub1(I, L, connectivity, sop); + connectedcomponents::NoOp sop; return connectedComponents_sub1(I, L, connectivity, sop); }else{ CV_Assert(false); return 0; @@ -429,9 +421,9 @@ int connectedComponentsWithStats(InputArray _I, OutputArray _L, OutputArray stat _L.create(I.size(), CV_MAT_TYPE(ltype)); cv::Mat L = _L.getMat(); if(ltype == CV_16U){ - connectedcomponents::CCStatsOp sop(statsv, centroids); return connectedComponents_sub1(I, L, connectivity, sop); + connectedcomponents::CCStatsOp sop(statsv, centroids); return connectedComponents_sub1(I, L, connectivity, sop); }else if(ltype == CV_32S){ - connectedcomponents::CCStatsOp sop(statsv, centroids); return connectedComponents_sub1(I, L, connectivity, sop); + connectedcomponents::CCStatsOp sop(statsv, centroids); return connectedComponents_sub1(I, L, connectivity, sop); }else{ CV_Assert(false); return 0; From ad0bfdfb25f379fa269e557c1c8565f1d10ba992 Mon Sep 17 00:00:00 2001 From: Jason Newton Date: Sat, 15 Dec 2012 03:37:24 -0800 Subject: [PATCH 11/34] disable windows build warning for connectedcomponents template argument comparisons --- modules/imgproc/src/connectedcomponents.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/modules/imgproc/src/connectedcomponents.cpp b/modules/imgproc/src/connectedcomponents.cpp index e0ad06364..97da8824d 100644 --- a/modules/imgproc/src/connectedcomponents.cpp +++ b/modules/imgproc/src/connectedcomponents.cpp @@ -43,6 +43,10 @@ #include "precomp.hpp" #include +#if defined _MSC_VER +#pragma warning(disable: 4127) +#endif + namespace cv{ namespace connectedcomponents{ From 1eae455acb9e3275657bd6ec8e36a92c30e2ccbd Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Sat, 15 Dec 2012 23:14:50 +0400 Subject: [PATCH 12/34] fixed build warnings from VS; hopefully, fixes Android build too --- .../include/opencv2/imgproc/imgproc.hpp | 17 ++- modules/imgproc/src/connectedcomponents.cpp | 118 +++++++----------- 2 files changed, 57 insertions(+), 78 deletions(-) diff --git a/modules/imgproc/include/opencv2/imgproc/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc/imgproc.hpp index 6be7ef6d1..284b25482 100644 --- a/modules/imgproc/include/opencv2/imgproc/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc/imgproc.hpp @@ -1104,12 +1104,17 @@ CV_EXPORTS_W void matchTemplate( InputArray image, InputArray templ, 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, int ltype=CV_32S); -CV_EXPORTS_W int connectedComponentsWithStats(InputArray image, OutputArray labels, OutputArray stats, OutputArray centroids, int connectivity = 8, int ltype=CV_32S); - +// 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, 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 enum diff --git a/modules/imgproc/src/connectedcomponents.cpp b/modules/imgproc/src/connectedcomponents.cpp index 97da8824d..d6bd125b0 100644 --- a/modules/imgproc/src/connectedcomponents.cpp +++ b/modules/imgproc/src/connectedcomponents.cpp @@ -43,22 +43,16 @@ #include "precomp.hpp" #include -#if defined _MSC_VER -#pragma warning(disable: 4127) -#endif - namespace cv{ namespace connectedcomponents{ - template struct NoOp{ NoOp(){ } - void init(const LabelT labels){ - (void) labels; + void init(int /*labels*/){ } inline - void operator()(int r, int c, LabelT l){ + void operator()(int r, int c, int l){ (void) r; (void) c; (void) l; @@ -69,38 +63,35 @@ namespace cv{ uint64 x, y; Point2ui64(uint64 _x, uint64 _y):x(_x), y(_y){} }; - template + struct CCStatsOp{ - OutputArray _mstatsv; + const _OutputArray* _mstatsv; cv::Mat statsv; - OutputArray _mcentroidsv; + const _OutputArray* _mcentroidsv; cv::Mat centroidsv; std::vector integrals; - CCStatsOp(OutputArray _statsv, OutputArray _centroidsv): _mstatsv(_statsv), _mcentroidsv(_centroidsv){ + CCStatsOp(OutputArray _statsv, OutputArray _centroidsv): _mstatsv(&_statsv), _mcentroidsv(&_centroidsv){ } inline - void init(const LabelT nlabels){ - _mstatsv.create(cv::Size(nlabels, CC_STAT_MAX), cv::DataType::type); - statsv = _mstatsv.getMat(); - _mcentroidsv.create(cv::Size(nlabels, 2), cv::DataType::type); - centroidsv = _mcentroidsv.getMat(); + void init(int nlabels){ + _mstatsv->create(cv::Size(nlabels, CC_STAT_MAX), cv::DataType::type); + statsv = _mstatsv->getMat(); + _mcentroidsv->create(cv::Size(nlabels, 2), cv::DataType::type); + centroidsv = _mcentroidsv->getMat(); for(int l = 0; l < (int) nlabels; ++l){ - unsigned int *row = (unsigned int *) &statsv.at(l, 0); - row[CC_STAT_LEFT] = std::numeric_limits::max(); - row[CC_STAT_TOP] = std::numeric_limits::max(); - row[CC_STAT_WIDTH] = std::numeric_limits::min(); - row[CC_STAT_HEIGHT] = std::numeric_limits::min(); - //row[CC_STAT_CX] = 0; - //row[CC_STAT_CY] = 0; + int *row = (int *) &statsv.at(l, 0); + row[CC_STAT_LEFT] = INT_MAX; + row[CC_STAT_TOP] = INT_MAX; + row[CC_STAT_WIDTH] = INT_MIN; + row[CC_STAT_HEIGHT] = INT_MIN; row[CC_STAT_AREA] = 0; } integrals.resize(nlabels, Point2ui64(0, 0)); } - void operator()(int r, int c, LabelT l){ + void operator()(int r, int c, int l){ int *row = &statsv.at(l, 0); - unsigned int *urow = (unsigned int *) row; if(c > row[CC_STAT_WIDTH]){ row[CC_STAT_WIDTH] = c; }else{ @@ -115,14 +106,14 @@ namespace cv{ row[CC_STAT_TOP] = r; } } - urow[CC_STAT_AREA]++; + row[CC_STAT_AREA]++; Point2ui64 &integral = integrals[l]; integral.x += c; integral.y += r; } void finish(){ for(int l = 0; l < statsv.rows; ++l){ - unsigned int *row = (unsigned int *) &statsv.at(l, 0); + int *row = &statsv.at(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]); @@ -130,8 +121,9 @@ namespace cv{ Point2ui64 &integral = integrals[l]; double *centroid = ¢roidsv.at(l, 0); - centroid[0] = double(integral.x) / row[CC_STAT_AREA]; - centroid[1] = double(integral.y) / row[CC_STAT_AREA]; + double area = ((unsigned*)row)[CC_STAT_AREA]; + centroid[0] = double(integral.x) / area; + centroid[1] = double(integral.y) / area; } } }; @@ -207,11 +199,12 @@ namespace cv{ const int G4[2][2] = {{1, 0}, {0, -1}};//b, d neighborhoods //reference for 8-way: {{-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, int connectivity = 8> + template struct LabelingImpl{ - LabelT operator()(const cv::Mat &I, cv::Mat &L, StatsOp &sop){ + LabelT operator()(const cv::Mat &I, cv::Mat &L, int connectivity, StatsOp &sop){ CV_Assert(L.rows == I.rows); CV_Assert(L.cols == I.cols); + CV_Assert(connectivity == 8 || connectivity == 4); const int rows = L.rows; const int cols = L.cols; size_t Plength = (size_t(rows + 3 - 1)/3) * (size_t(cols + 3 - 1)/3); @@ -295,7 +288,6 @@ namespace cv{ } }else{ //B & D only - assert(connectivity == 4); const int b = 0; const int d = 1; const bool T_b_r = (r_i - G4[b][0]) >= 0; @@ -368,70 +360,52 @@ int connectedComponents_sub1(const cv::Mat &I, cv::Mat &L, int connectivity, Sta using connectedcomponents::LabelingImpl; //warn if L's depth is not sufficient? + CV_Assert(iDepth == CV_8U || iDepth == CV_8S); + if(lDepth == CV_8U){ - if(iDepth == CV_8U || iDepth == CV_8S){ - if(connectivity == 4){ - return (int) LabelingImpl()(I, L, sop); - }else{ - return (int) LabelingImpl()(I, L, sop); - } - }else{ - CV_Assert(false); - } + return (int) LabelingImpl()(I, L, connectivity, sop); }else if(lDepth == CV_16U){ - if(iDepth == CV_8U || iDepth == CV_8S){ - if(connectivity == 4){ - return (int) LabelingImpl()(I, L, sop); - }else{ - return (int) LabelingImpl()(I, L, sop); - } - }else{ - CV_Assert(false); - } + return (int) LabelingImpl()(I, L, connectivity, sop); }else if(lDepth == CV_32S){ //note that signed types don't really make sense here and not being able to use unsigned matters for scientific projects //OpenCV: how should we proceed? .at typechecks in debug mode - if(iDepth == CV_8U || iDepth == CV_8S){ - if(connectivity == 4){ - return (int) LabelingImpl()(I, L, sop); - }else{ - return (int) LabelingImpl()(I, L, sop); - } - }else{ - CV_Assert(false); - } + return (int) LabelingImpl()(I, L, connectivity, sop); } CV_Error(CV_StsUnsupportedFormat, "unsupported label/image type"); return -1; } -int connectedComponents(InputArray _I, OutputArray _L, int connectivity, int ltype){ +} + +int cv::connectedComponents(InputArray _I, OutputArray _L, int connectivity, int ltype){ const cv::Mat I = _I.getMat(); - _L.create(I.size(), CV_MAT_TYPE(ltype)); + _L.create(I.size(), CV_MAT_DEPTH(ltype)); cv::Mat L = _L.getMat(); + connectedcomponents::NoOp sop; if(ltype == CV_16U){ - connectedcomponents::NoOp sop; return connectedComponents_sub1(I, L, connectivity, sop); + return connectedComponents_sub1(I, L, connectivity, sop); }else if(ltype == CV_32S){ - connectedcomponents::NoOp sop; return connectedComponents_sub1(I, L, connectivity, sop); + return connectedComponents_sub1(I, L, connectivity, sop); }else{ - CV_Assert(false); + CV_Error(CV_StsUnsupportedFormat, "the type of labels must be 16u or 32s"); return 0; } } -int connectedComponentsWithStats(InputArray _I, OutputArray _L, OutputArray statsv, OutputArray centroids, int connectivity, int ltype){ +int cv::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)); + _L.create(I.size(), CV_MAT_DEPTH(ltype)); cv::Mat L = _L.getMat(); + connectedcomponents::CCStatsOp sop(statsv, centroids); if(ltype == CV_16U){ - connectedcomponents::CCStatsOp sop(statsv, centroids); return connectedComponents_sub1(I, L, connectivity, sop); + return connectedComponents_sub1(I, L, connectivity, sop); }else if(ltype == CV_32S){ - connectedcomponents::CCStatsOp sop(statsv, centroids); return connectedComponents_sub1(I, L, connectivity, sop); + return connectedComponents_sub1(I, L, connectivity, sop); }else{ - CV_Assert(false); + CV_Error(CV_StsUnsupportedFormat, "the type of labels must be 16u or 32s"); return 0; } } - -} From 5f86eb8d63f1684088940d36015ee0bb79436484 Mon Sep 17 00:00:00 2001 From: Jason Newton Date: Sun, 16 Dec 2012 00:44:32 -0800 Subject: [PATCH 13/34] proper dimensions from cv::Size in output stats/centroid --- modules/imgproc/src/connectedcomponents.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/imgproc/src/connectedcomponents.cpp b/modules/imgproc/src/connectedcomponents.cpp index d6bd125b0..c07249b47 100644 --- a/modules/imgproc/src/connectedcomponents.cpp +++ b/modules/imgproc/src/connectedcomponents.cpp @@ -75,9 +75,9 @@ namespace cv{ } inline void init(int nlabels){ - _mstatsv->create(cv::Size(nlabels, CC_STAT_MAX), cv::DataType::type); + _mstatsv->create(cv::Size(CC_STAT_MAX, nlabels), cv::DataType::type); statsv = _mstatsv->getMat(); - _mcentroidsv->create(cv::Size(nlabels, 2), cv::DataType::type); + _mcentroidsv->create(cv::Size(2, nlabels), cv::DataType::type); centroidsv = _mcentroidsv->getMat(); for(int l = 0; l < (int) nlabels; ++l){ From e1b60aa4e326b900b63596c19c50ad97a8de98eb Mon Sep 17 00:00:00 2001 From: Jason Newton Date: Sun, 16 Dec 2012 22:44:36 -0800 Subject: [PATCH 14/34] drop usage of macros... the type is already there! --- modules/imgproc/src/connectedcomponents.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/imgproc/src/connectedcomponents.cpp b/modules/imgproc/src/connectedcomponents.cpp index c07249b47..69655869c 100644 --- a/modules/imgproc/src/connectedcomponents.cpp +++ b/modules/imgproc/src/connectedcomponents.cpp @@ -380,7 +380,7 @@ int connectedComponents_sub1(const cv::Mat &I, cv::Mat &L, int connectivity, Sta int cv::connectedComponents(InputArray _I, OutputArray _L, int connectivity, int ltype){ const cv::Mat I = _I.getMat(); - _L.create(I.size(), CV_MAT_DEPTH(ltype)); + _L.create(I.size(), ltype); cv::Mat L = _L.getMat(); connectedcomponents::NoOp sop; if(ltype == CV_16U){ @@ -397,7 +397,7 @@ int cv::connectedComponentsWithStats(InputArray _I, OutputArray _L, OutputArray OutputArray centroids, int connectivity, int ltype) { const cv::Mat I = _I.getMat(); - _L.create(I.size(), CV_MAT_DEPTH(ltype)); + _L.create(I.size(), ltype); cv::Mat L = _L.getMat(); connectedcomponents::CCStatsOp sop(statsv, centroids); if(ltype == CV_16U){ From 31857082f4bbfb124b39399e8381efa2a93f0956 Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Mon, 17 Dec 2012 21:33:21 +0400 Subject: [PATCH 15/34] probably fixed build problems on Android --- modules/imgproc/src/connectedcomponents.cpp | 24 ++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/modules/imgproc/src/connectedcomponents.cpp b/modules/imgproc/src/connectedcomponents.cpp index 69655869c..4fee0aacd 100644 --- a/modules/imgproc/src/connectedcomponents.cpp +++ b/modules/imgproc/src/connectedcomponents.cpp @@ -378,32 +378,32 @@ int connectedComponents_sub1(const cv::Mat &I, cv::Mat &L, int connectivity, Sta } -int cv::connectedComponents(InputArray _I, OutputArray _L, int connectivity, int ltype){ - const cv::Mat I = _I.getMat(); - _L.create(I.size(), ltype); - cv::Mat L = _L.getMat(); +int cv::connectedComponents(InputArray _img, OutputArray _labels, int connectivity, int ltype){ + const cv::Mat img = _img.getMat(); + _labels.create(img.size(), CV_MAT_DEPTH(ltype)); + cv::Mat labels = _labels.getMat(); connectedcomponents::NoOp sop; if(ltype == CV_16U){ - return connectedComponents_sub1(I, L, connectivity, sop); + return connectedComponents_sub1(img, labels, connectivity, sop); }else if(ltype == CV_32S){ - return connectedComponents_sub1(I, L, connectivity, sop); + return connectedComponents_sub1(img, labels, connectivity, sop); }else{ CV_Error(CV_StsUnsupportedFormat, "the type of labels must be 16u or 32s"); return 0; } } -int cv::connectedComponentsWithStats(InputArray _I, OutputArray _L, OutputArray statsv, +int cv::connectedComponentsWithStats(InputArray _img, OutputArray _labels, OutputArray statsv, OutputArray centroids, int connectivity, int ltype) { - const cv::Mat I = _I.getMat(); - _L.create(I.size(), ltype); - cv::Mat L = _L.getMat(); + const cv::Mat img = _img.getMat(); + _labels.create(img.size(), CV_MAT_DEPTH(ltype)); + cv::Mat labels = _labels.getMat(); connectedcomponents::CCStatsOp sop(statsv, centroids); if(ltype == CV_16U){ - return connectedComponents_sub1(I, L, connectivity, sop); + return connectedComponents_sub1(img, labels, connectivity, sop); }else if(ltype == CV_32S){ - return connectedComponents_sub1(I, L, connectivity, sop); + return connectedComponents_sub1(img, labels, connectivity, sop); }else{ CV_Error(CV_StsUnsupportedFormat, "the type of labels must be 16u or 32s"); return 0; From 4cb25e9584e3349b41b85b183c44fd81028187c7 Mon Sep 17 00:00:00 2001 From: Jason Newton Date: Wed, 19 Dec 2012 14:55:46 -0800 Subject: [PATCH 16/34] update documentation to latest connected components interface --- ...uctural_analysis_and_shape_descriptors.rst | 54 ++++++++----------- .../include/opencv2/imgproc/imgproc.hpp | 6 +-- 2 files changed, 25 insertions(+), 35 deletions(-) diff --git a/modules/imgproc/doc/structural_analysis_and_shape_descriptors.rst b/modules/imgproc/doc/structural_analysis_and_shape_descriptors.rst index ad5c22cbb..9f45301c5 100644 --- a/modules/imgproc/doc/structural_analysis_and_shape_descriptors.rst +++ b/modules/imgproc/doc/structural_analysis_and_shape_descriptors.rst @@ -119,47 +119,37 @@ These values are proved to be invariants to the image scale, rotation, and refle .. seealso:: :ocv:func:`matchShapes` connectedComponents ------------ -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. +----------------------- +computes the connected components labeled image of boolean image ``image`` with 4 or 8 way connectivity - returns N, the total number of labels [0, N-1] where 0 represents the background label. ltype specifies the output label image type, an important consideration based on the total number of labels or alternatively the total number of pixels in the source image. -.. ocv:function:: uint64 connectedComponents(Mat &L, const Mat &I, int connectivity = 8) +.. ocv:function:: int connectedComponents(InputArray image, OutputArray labels, int connectivity = 8, int ltype=CV_32S) -.. ocv:function:: uint64 connectedComponentsWithStats(Mat &L, const Mat &I, std::vector &statsv, int connectivity = 8) +.. ocv:function:: int connectedComponentsWithStats(InputArray image, OutputArray labels, OutputArray stats, OutputArray centroids, int connectivity = 8, int ltype=CV_32S) - :param L: destitination Labeled image + :param image: the image to be labeled - :param I: the image to be labeled + :param labels: destination labeled image :param connectivity: 8 or 4 for 8-way or 4-way connectivity respectively - :param statsv: statistics for each label, including the background label + :param ltype: output image label type. Currently CV_32S and CV_16U are supported. -Statistics information such as bounding box, area, and centroid is exported via the ``ConnectComponentStats`` structure defined as: :: + :param statsv: statistics output for each label, including the background label, see below for available statistics. Statistics are accessed via statsv(label, COLUMN) where available columns are defined below. + + * **CC_STAT_LEFT** The leftmost (x) coordinate which is the inclusive start of the bounding box in the horizontal + direction. + + * **CC_STAT_TOP** The topmost (y) coordinate which is the inclusive start of the bounding box in the vertical + direction. + + * **CC_STAT_WIDTH** The horizontal size of the bounding box + + * **CC_STAT_HEIGHT** The vertical size of the bounding box + + * **CC_STAT_AREA** The total area (in pixels) of the connected component + + :param centroids: floating point centroid (x,y) output for each label, including the background label - class CV_EXPORTS ConnectedComponentStats - { - public: - //! lower left corner column - int lower_x; - //! lower left corner row - int lower_y; - //! upper right corner column - int upper_x; - //! upper right corner row - int upper_y; - //! centroid column - double centroid_x; - //! centroid row - double centroid_y; - //! sum of all columns where the image was non-zero - uint64 integral_x; - //! sum of all rows where the image was non-zero - uint64 integral_y; - //! count of all non-zero pixels - unsigned int area; - }; findContours ---------------- diff --git a/modules/imgproc/include/opencv2/imgproc/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc/imgproc.hpp index 284b25482..34df8f2fc 100644 --- a/modules/imgproc/include/opencv2/imgproc/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc/imgproc.hpp @@ -1104,12 +1104,12 @@ CV_EXPORTS_W void matchTemplate( InputArray image, InputArray templ, 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 +// computes the connected components labeled image of boolean image ``image`` // 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 +// ltype specifies the output label image type, an important // consideration based on the total number of labels or -// alternatively the total number of pixels. +// alternatively the total number of pixels in the source image. 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, From 5023afffc714a2a7581ca87c861c557e184d720e Mon Sep 17 00:00:00 2001 From: Kirill Kornyakov Date: Wed, 26 Dec 2012 10:33:02 +0400 Subject: [PATCH 17/34] Removed hack from perf test on HoughLines, since I hope it is fixed by pr263 --- modules/imgproc/perf/perf_houghLines.cpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/modules/imgproc/perf/perf_houghLines.cpp b/modules/imgproc/perf/perf_houghLines.cpp index c6cc6e439..4e6b5b3fb 100644 --- a/modules/imgproc/perf/perf_houghLines.cpp +++ b/modules/imgproc/perf/perf_houghLines.cpp @@ -36,18 +36,5 @@ PERF_TEST_P(Image_RhoStep_ThetaStep_Threshold, HoughLines, TEST_CYCLE() HoughLines(image, lines, rhoStep, thetaStep, threshold); -#ifdef WIN32 - //FIXME: ugly fix to make sanity check pass on Win32, must be investigated, issue #2617 - if (lines.cols == 2015) - { - lines = lines(Rect(0, 0, lines.cols - 1, lines.rows)); - SANITY_CHECK(lines, 800.0); - } - else - { - SANITY_CHECK(lines); - } -#else SANITY_CHECK(lines); -#endif } From aabbe11e64c0d98d8a12fb80f4c932aabff4893c Mon Sep 17 00:00:00 2001 From: Andrey Kamaev Date: Mon, 12 Nov 2012 14:42:28 +0400 Subject: [PATCH 18/34] Improve function arguments parsing and checking * always use "argN" names for unnamed arguments * honor space symbol between typename and "*", "&" symbols * fix indent errors --- doc/check_docs2.py | 3 ++ modules/java/generator/rst_parser.py | 69 +++++++++++++++------------- modules/python/src2/hdr_parser.py | 4 +- 3 files changed, 41 insertions(+), 35 deletions(-) diff --git a/doc/check_docs2.py b/doc/check_docs2.py index bf0375459..29e20f7bc 100755 --- a/doc/check_docs2.py +++ b/doc/check_docs2.py @@ -116,6 +116,8 @@ def compareSignatures(f, s): sarg = arg[1] ftype = re.sub(r"\b(cv|std)::", "", (farg[0] or "")) stype = re.sub(r"\b(cv|std)::", "", (sarg[0] or "")) + ftype = re.sub(r" (&|\*)$", "\\1", ftype) + stype = re.sub(r" (&|\*)$", "\\1", stype) if ftype != stype: return False, "type of argument #" + str(idx+1) + " mismatch" fname = farg[1] or "arg" + str(idx) @@ -151,6 +153,7 @@ def formatSignature(s): if idx > 0: _str += ", " argtype = re.sub(r"\bcv::", "", arg[0]) + argtype = re.sub(r" (&|\*)$", "\\1", argtype) bidx = argtype.find('[') if bidx < 0: _str += argtype + " " diff --git a/modules/java/generator/rst_parser.py b/modules/java/generator/rst_parser.py index f4ef58190..a9f5e04c9 100755 --- a/modules/java/generator/rst_parser.py +++ b/modules/java/generator/rst_parser.py @@ -11,7 +11,7 @@ params_blacklist = { "fromarray" : ("object", "allowND"), # python only function "reprojectImageTo3D" : ("ddepth"), # python only argument "composeRT" : ("d*d*"), # wildchards in parameter names are not supported by this parser - "CvSVM::train_auto" : ("\*Grid"), # wildchards in parameter names are not supported by this parser + "CvSVM::train_auto" : ("\\*Grid"), # wildchards in parameter names are not supported by this parser "error" : "args", # parameter of supporting macro "getConvertElem" : ("from", "cn", "to", "beta", "alpha"), # arguments of returned functions "gpu::swapChannels" : ("dstOrder") # parameter is not parsed correctly by the hdr_parser @@ -71,7 +71,8 @@ class DeclarationParser(object): def isready(self): return self.balance == 0 - def getLang(self, line): + @classmethod + def getLang(cls, line): if line.startswith(".. ocv:function::"): return "C++" if line.startswith(".. ocv:cfunction::"): @@ -98,7 +99,7 @@ class ParamParser(object): offset = line.find(":param") assert offset > 0 self.prefix = line[:offset] - assert self.prefix==" "*len(self.prefix), ":param definition should be prefixed with spaces" + assert self.prefix == " "*len(self.prefix), ":param definition should be prefixed with spaces" line = line[offset + 6:].lstrip() name_end = line.find(":") assert name_end > 0 @@ -115,7 +116,8 @@ class ParamParser(object): else: self.active = False - def hasDeclaration(self, line): + @classmethod + def hasDeclaration(cls, line): return line.lstrip().startswith(":param") class RstParser(object): @@ -177,6 +179,7 @@ class RstParser(object): was_code_line = False fdecl = DeclarationParser() pdecl = ParamParser() + ll = None for l in lines: # read tail of function/method declaration if needed @@ -189,7 +192,7 @@ class RstParser(object): # continue capture seealso if capturing_seealso: if not l or l.startswith(" "): - seealso = func.get("seealso",[]) + seealso = func.get("seealso", []) seealso.extend(l.split(",")) func["seealso"] = seealso continue @@ -206,9 +209,7 @@ class RstParser(object): if skip_code_lines: if not l: continue - if l.startswith(" "): - None - else: + if not l.startswith(" "): skip_code_lines = False if ll.startswith(".. code-block::") or ll.startswith(".. image::"): @@ -248,7 +249,7 @@ class RstParser(object): if ll.endswith(".. seealso::"): capturing_seealso = True else: - seealso = func.get("seealso",[]) + seealso = func.get("seealso", []) seealso.extend(ll[ll.find("::")+2:].split(",")) func["seealso"] = seealso continue @@ -300,12 +301,12 @@ class RstParser(object): if (was_code_line): func["long"] = func.get("long", "") + "\n" + ll + "\n" else: - was_code_line = True; + was_code_line = True func["long"] = func.get("long", "") + ll +"\n\n\n // C++ code:\n\n" else: if (was_code_line): - func["long"] = func.get("long", "") + "\n" + ll + "\n\n"; - was_code_line = False; + func["long"] = func.get("long", "") + "\n" + ll + "\n\n" + was_code_line = False else: func["long"] = func.get("long", "") + "\n" + ll # endfor l in lines @@ -377,7 +378,8 @@ class RstParser(object): if len(lines) > 1: self.parse_section_safe(module_name, fname, doc, flineno, lines) - def parse_namespace(self, func, section_name): + @classmethod + def parse_namespace(cls, func, section_name): known_namespaces = ["cv", "gpu", "flann"] l = section_name.strip() for namespace in known_namespaces: @@ -390,7 +392,7 @@ class RstParser(object): if decl.fdecl.endswith(";"): print >> sys.stderr, "RST parser error E%03d: unexpected semicolon at the end of declaration in \"%s\" at %s:%s" \ % (ERROR_011_EOLEXPECTED, func["name"], func["file"], func["line"]) - decls = func.get("decls",[]) + decls = func.get("decls", []) if (decl.lang == "C++" or decl.lang == "C"): rst_decl = self.cpp_parser.parse_func_decl_no_wrap(decl.fdecl) decls.append( [decl.lang, decl.fdecl, rst_decl] ) @@ -398,8 +400,9 @@ class RstParser(object): decls.append( [decl.lang, decl.fdecl] ) func["decls"] = decls - def add_new_pdecl(self, func, decl): - params = func.get("params",{}) + @classmethod + def add_new_pdecl(cls, func, decl): + params = func.get("params", {}) if decl.name in params: if show_errors: #check black_list @@ -416,8 +419,8 @@ class RstParser(object): print >> out, "SKIPPED DEFINITION:" print >> out, "name: %s" % (func.get("name","~empty~")) print >> out, "file: %s:%s" % (func.get("file","~empty~"), func.get("line","~empty~")) - print >> out, "is class: %s" % func.get("isclass",False) - print >> out, "is struct: %s" % func.get("isstruct",False) + print >> out, "is class: %s" % func.get("isclass", False) + print >> out, "is struct: %s" % func.get("isstruct", False) print >> out, "module: %s" % func.get("module","~unknown~") print >> out, "namespace: %s" % func.get("namespace", "~empty~") print >> out, "class: %s" % (func.get("class","~empty~")) @@ -426,7 +429,7 @@ class RstParser(object): if "decls" in func: print >> out, "declarations:" for d in func["decls"]: - print >> out, " %7s: %s" % (d[0], re.sub(r"[ ]+", " ", d[1])) + print >> out, " %7s: %s" % (d[0], re.sub(r"[ ]+", " ", d[1])) if "seealso" in func: print >> out, "seealso: ", func["seealso"] if "params" in func: @@ -437,8 +440,8 @@ class RstParser(object): print >> out def validate(self, func): - if func.get("decls",None) is None: - if not func.get("isclass",False) and not func.get("isstruct",False): + if func.get("decls", None) is None: + if not func.get("isclass", False) and not func.get("isstruct", False): return False if func["name"] in self.definitions: if show_errors: @@ -448,7 +451,7 @@ class RstParser(object): return self.validateParams(func) def validateParams(self, func): - documentedParams = func.get("params",{}).keys() + documentedParams = func.get("params", {}).keys() params = [] for decl in func.get("decls", []): @@ -486,11 +489,11 @@ class RstParser(object): if "class" in func: func["class"] = self.normalizeText(func["class"]) if "brief" in func: - func["brief"] = self.normalizeText(func.get("brief",None)) + func["brief"] = self.normalizeText(func.get("brief", None)) if not func["brief"]: del func["brief"] if "long" in func: - func["long"] = self.normalizeText(func.get("long",None)) + func["long"] = self.normalizeText(func.get("long", None)) if not func["long"]: del func["long"] if "decls" in func: @@ -518,7 +521,7 @@ class RstParser(object): del func["seealso"] # special case for old C functions - section name should omit "cv" prefix - if not func.get("isclass",False) and not func.get("isstruct",False): + if not func.get("isclass", False) and not func.get("isstruct", False): self.fixOldCFunctionName(func) return func @@ -616,7 +619,7 @@ class RstParser(object): s = re.sub(r" +", " ", s) # restore math - s = re.sub(r" *
*","\n", s) + s = re.sub(r" *
*", "\n", s) # remove extra space before . s = re.sub(r"[\n ]+\.", ".", s) @@ -642,13 +645,13 @@ class RstParser(object): classes = 0 structs = 0 for name, d in self.definitions.items(): - if d.get("isclass", False): - classes += 1 - elif d.get("isstruct", False): - structs += 1 - else: - for decl in d.get("decls",[]): - stat[decl[0]] = stat.get(decl[0],0) + 1 + if d.get("isclass", False): + classes += 1 + elif d.get("isstruct", False): + structs += 1 + else: + for decl in d.get("decls", []): + stat[decl[0]] = stat.get(decl[0], 0) + 1 print print " classes documented: %s" % classes diff --git a/modules/python/src2/hdr_parser.py b/modules/python/src2/hdr_parser.py index 090ed6f64..8335b0c52 100755 --- a/modules/python/src2/hdr_parser.py +++ b/modules/python/src2/hdr_parser.py @@ -337,10 +337,10 @@ class CppHeaderParser(object): atype = arg[:pos+1].strip() if aname.endswith("&") or aname.endswith("*") or (aname in ["int", "string", "Mat"]): atype = (atype + " " + aname).strip() - aname = "param" + aname = "" else: atype = arg - aname = "param" + aname = "" if aname.endswith("]"): bidx = aname.find('[') atype += aname[bidx:] From b401c6a0c3dbc5bfcce44e8f773a99869f78300e Mon Sep 17 00:00:00 2001 From: Andrey Kamaev Date: Wed, 26 Dec 2012 17:51:04 +0400 Subject: [PATCH 19/34] Fix discrepancies between function signatures in headers and documentation --- doc/check_docs2.py | 6 +- modules/contrib/doc/retina/index.rst | 2 +- .../include/opencv2/contrib/retina.hpp | 8 +- .../doc/feature_detection_and_description.rst | 14 +- modules/ocl/doc/image_filtering.rst | 22 +-- modules/ocl/doc/image_processing.rst | 28 ++-- modules/ocl/doc/matrix_reductions.rst | 10 +- modules/ocl/doc/object_detection.rst | 11 +- modules/ocl/doc/operations_on_matrices.rst | 126 ++++++++++-------- .../doc/structures_and_utility_functions.rst | 6 +- modules/ocl/include/opencv2/ocl/ocl.hpp | 26 ++-- modules/python/src2/hdr_parser.py | 2 + 12 files changed, 136 insertions(+), 125 deletions(-) diff --git a/doc/check_docs2.py b/doc/check_docs2.py index 29e20f7bc..0a29b5038 100755 --- a/doc/check_docs2.py +++ b/doc/check_docs2.py @@ -116,8 +116,8 @@ def compareSignatures(f, s): sarg = arg[1] ftype = re.sub(r"\b(cv|std)::", "", (farg[0] or "")) stype = re.sub(r"\b(cv|std)::", "", (sarg[0] or "")) - ftype = re.sub(r" (&|\*)$", "\\1", ftype) - stype = re.sub(r" (&|\*)$", "\\1", stype) + ftype = re.sub(r"\s+(\*|&)$", "\\1", ftype) + stype = re.sub(r"\s+(\*|&)$", "\\1", stype) if ftype != stype: return False, "type of argument #" + str(idx+1) + " mismatch" fname = farg[1] or "arg" + str(idx) @@ -153,7 +153,7 @@ def formatSignature(s): if idx > 0: _str += ", " argtype = re.sub(r"\bcv::", "", arg[0]) - argtype = re.sub(r" (&|\*)$", "\\1", argtype) + argtype = re.sub(r"\s+(\*|&)$", "\\1", arg[0]) bidx = argtype.find('[') if bidx < 0: _str += argtype + " " diff --git a/modules/contrib/doc/retina/index.rst b/modules/contrib/doc/retina/index.rst index 913f7d107..d80e45792 100644 --- a/modules/contrib/doc/retina/index.rst +++ b/modules/contrib/doc/retina/index.rst @@ -208,7 +208,7 @@ Retina::getMagno Retina::getParameters +++++++++++++++++++++ -.. ocv:function:: Retina::RetinaParameters Retina::getParameters() +.. ocv:function:: struct Retina::RetinaParameters Retina::getParameters() Retrieve the current parameters values in a *Retina::RetinaParameters* structure diff --git a/modules/contrib/include/opencv2/contrib/retina.hpp b/modules/contrib/include/opencv2/contrib/retina.hpp index 3ee291a8b..ab8bc360c 100644 --- a/modules/contrib/include/opencv2/contrib/retina.hpp +++ b/modules/contrib/include/opencv2/contrib/retina.hpp @@ -203,10 +203,10 @@ public: */ void setup(RetinaParameters newParameters); - /** - * @return the current parameters setup - */ - struct Retina::RetinaParameters getParameters(); + /** + * @return the current parameters setup + */ + struct Retina::RetinaParameters getParameters(); /** * parameters setup display method diff --git a/modules/ocl/doc/feature_detection_and_description.rst b/modules/ocl/doc/feature_detection_and_description.rst index aa2ed857c..a6416d4e6 100644 --- a/modules/ocl/doc/feature_detection_and_description.rst +++ b/modules/ocl/doc/feature_detection_and_description.rst @@ -36,8 +36,8 @@ Finds edges in an image using the [Canny86]_ algorithm. .. seealso:: :ocv:func:`Canny` -ocl::BruteForceMatcher_OCL --------------------------- +ocl::BruteForceMatcher_OCL_base +------------------------------- .. ocv:class:: ocl::BruteForceMatcher_OCL_base Brute-force descriptor matcher. For each descriptor in the first set, this matcher finds the closest descriptor in the second set by trying each one. This descriptor matcher supports masking permissible matches between descriptor sets. :: @@ -162,7 +162,7 @@ Finds the best match for each descriptor from a query set with train descriptors .. ocv:function:: void ocl::BruteForceMatcher_OCL_base::match(const oclMat& query, std::vector& matches, const std::vector& masks = std::vector()) -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::matchCollection(const oclMat& query, const oclMat& trainCollection, oclMat& trainIdx, oclMat& imgIdx, oclMat& distance, const oclMat& masks) +.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::matchCollection( const oclMat& query, const oclMat& trainCollection, oclMat& trainIdx, oclMat& imgIdx, oclMat& distance, const oclMat& masks=oclMat() ) .. seealso:: :ocv:func:`DescriptorMatcher::match` @@ -175,15 +175,13 @@ Performs a GPU collection of train descriptors and masks in a suitable format fo .. ocv:function:: void ocl::BruteForceMatcher_OCL_base::makeGpuCollection(oclMat& trainCollection, oclMat& maskCollection, const vector& masks = std::vector()) - ocl::BruteForceMatcher_OCL_base::matchDownload ---------------------------------------------- Downloads matrices obtained via :ocv:func:`ocl::BruteForceMatcher_OCL_base::matchSingle` or :ocv:func:`ocl::BruteForceMatcher_OCL_base::matchCollection` to vector with :ocv:class:`DMatch`. -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::matchDownload(const oclMat& trainIdx, const oclMat& distance, std::vector&matches) - -.. ocv:function:: void ocl::BruteForceMatcher_OCL_base::matchDownload(const oclMat& trainIdx, oclMat& imgIdx, const oclMat& distance, std::vector&matches) +.. ocv:function:: static void ocl::BruteForceMatcher_OCL_base::matchDownload( const oclMat& trainIdx, const oclMat& distance, std::vector& matches ) +.. ocv:function:: static void ocl::BruteForceMatcher_OCL_base::matchDownload( const oclMat& trainIdx, const oclMat& imgIdx, const oclMat& distance, std::vector& matches ) ocl::BruteForceMatcher_OCL_base::matchConvert @@ -310,7 +308,7 @@ If ``compactResult`` is ``true`` , the ``matches`` vector does not contain match ocl::HOGDescriptor ------------------ -.. ocv:class:: ocl::HOGDescriptor +.. ocv:struct:: ocl::HOGDescriptor The class implements Histogram of Oriented Gradients ([Dalal2005]_) object detector. :: diff --git a/modules/ocl/doc/image_filtering.rst b/modules/ocl/doc/image_filtering.rst index 20e90c3d9..ca97d3a93 100644 --- a/modules/ocl/doc/image_filtering.rst +++ b/modules/ocl/doc/image_filtering.rst @@ -7,7 +7,7 @@ ocl::Sobel ------------------ Returns void -.. ocv:function:: void Sobel(const oclMat &src, oclMat &dst, int ddepth, int dx, int dy, int ksize = 3, double scale = 1, double delta = 0.0, int bordertype = BORDER_DEFAULT) +.. ocv:function:: void ocl::Sobel(const oclMat &src, oclMat &dst, int ddepth, int dx, int dy, int ksize = 3, double scale = 1, double delta = 0.0, int bordertype = BORDER_DEFAULT) :param src: The source image @@ -33,7 +33,7 @@ ocl::Scharr ------------------ Returns void -.. ocv:function:: void Scharr(const oclMat &src, oclMat &dst, int ddepth, int dx, int dy, double scale = 1, double delta = 0.0, int bordertype = BORDER_DEFAULT) +.. ocv:function:: void ocl::Scharr(const oclMat &src, oclMat &dst, int ddepth, int dx, int dy, double scale = 1, double delta = 0.0, int bordertype = BORDER_DEFAULT) :param src: The source image @@ -57,7 +57,7 @@ ocl::GaussianBlur ------------------ Returns void -.. ocv:function:: void GaussianBlur(const oclMat &src, oclMat &dst, Size ksize, double sigma1, double sigma2 = 0, int bordertype = BORDER_DEFAULT) +.. ocv:function:: void ocl::GaussianBlur(const oclMat &src, oclMat &dst, Size ksize, double sigma1, double sigma2 = 0, int bordertype = BORDER_DEFAULT) :param src: The source image @@ -75,7 +75,7 @@ ocl::boxFilter ------------------ Returns void -.. ocv:function:: void boxFilter(const oclMat &src, oclMat &dst, int ddepth, Size ksize, Point anchor = Point(-1, -1), int borderType = BORDER_DEFAULT) +.. ocv:function:: void ocl::boxFilter(const oclMat &src, oclMat &dst, int ddepth, Size ksize, Point anchor = Point(-1, -1), int borderType = BORDER_DEFAULT) :param src: The source image @@ -95,7 +95,7 @@ ocl::Laplacian ------------------ Returns void -.. ocv:function:: void Laplacian(const oclMat &src, oclMat &dst, int ddepth, int ksize = 1, double scale = 1) +.. ocv:function:: void ocl::Laplacian(const oclMat &src, oclMat &dst, int ddepth, int ksize = 1, double scale = 1) :param src: The source image @@ -113,7 +113,7 @@ ocl::convolve ------------------ Returns void -.. ocv:function:: void convolve(const oclMat &image, const oclMat &temp1, oclMat &result) +.. ocv:function:: void ocl::convolve(const oclMat &image, const oclMat &temp1, oclMat &result) :param image: The source image @@ -127,7 +127,7 @@ ocl::bilateralFilter -------------------- Returns void -.. ocv:function:: void bilateralFilter(const oclMat &src, oclMat &dst, int d, double sigmaColor, double sigmaSpave, int borderType=BORDER_DEFAULT) +.. ocv:function:: void ocl::bilateralFilter(const oclMat &src, oclMat &dst, int d, double sigmaColor, double sigmaSpave, int borderType=BORDER_DEFAULT) :param src: The source image @@ -147,7 +147,7 @@ ocl::copyMakeBorder -------------------- Returns void -.. ocv:function:: void copyMakeBorder(const oclMat &src, oclMat &dst, int top, int bottom, int left, int right, int boardtype, const Scalar &value = Scalar()) +.. ocv:function:: void ocl::copyMakeBorder(const oclMat &src, oclMat &dst, int top, int bottom, int left, int right, int boardtype, const Scalar &value = Scalar()) :param src: The source image @@ -165,7 +165,7 @@ ocl::dilate ------------------ Returns void -.. ocv:function:: void dilate( const oclMat &src, oclMat &dst, const Mat &kernel, Point anchor = Point(-1, -1), int iterations = 1, int borderType = BORDER_CONSTANT, const Scalar &borderValue = morphologyDefaultBorderValue()) +.. ocv:function:: void ocl::dilate( const oclMat &src, oclMat &dst, const Mat &kernel, Point anchor = Point(-1, -1), int iterations = 1, int borderType = BORDER_CONSTANT, const Scalar &borderValue = morphologyDefaultBorderValue()) :param src: The source image @@ -187,7 +187,7 @@ ocl::erode ------------------ Returns void -.. ocv:function:: void erode( const oclMat &src, oclMat &dst, const Mat &kernel, Point anchor = Point(-1, -1), int iterations = 1, int borderType = BORDER_CONSTANT, const Scalar &borderValue = morphologyDefaultBorderValue()) +.. ocv:function:: void ocl::erode( const oclMat &src, oclMat &dst, const Mat &kernel, Point anchor = Point(-1, -1), int iterations = 1, int borderType = BORDER_CONSTANT, const Scalar &borderValue = morphologyDefaultBorderValue()) :param src: The source image @@ -209,7 +209,7 @@ ocl::morphologyEx ------------------ Returns void -.. ocv:function:: void morphologyEx( const oclMat &src, oclMat &dst, int op, const Mat &kernel, Point anchor = Point(-1, -1), int iterations = 1, int borderType = BORDER_CONSTANT, const Scalar &borderValue = morphologyDefaultBorderValue()) +.. ocv:function:: void ocl::morphologyEx( const oclMat &src, oclMat &dst, int op, const Mat &kernel, Point anchor = Point(-1, -1), int iterations = 1, int borderType = BORDER_CONSTANT, const Scalar &borderValue = morphologyDefaultBorderValue()) :param src: The source image diff --git a/modules/ocl/doc/image_processing.rst b/modules/ocl/doc/image_processing.rst index 461fb98a5..94712e091 100644 --- a/modules/ocl/doc/image_processing.rst +++ b/modules/ocl/doc/image_processing.rst @@ -7,7 +7,7 @@ ocl::cornerHarris ------------------ Returns void -.. ocv:function:: void cornerHarris(const oclMat &src, oclMat &dst, int blockSize, int ksize, double k, int bordertype = cv::BORDER_DEFAULT) +.. ocv:function:: void ocl::cornerHarris(const oclMat &src, oclMat &dst, int blockSize, int ksize, double k, int bordertype = cv::BORDER_DEFAULT) :param src: Source image. Only CV_8UC1 and CV_32FC1 images are supported now. @@ -27,7 +27,7 @@ ocl::cornerMinEigenVal ------------------------ Returns void -.. ocv:function:: void cornerMinEigenVal(const oclMat &src, oclMat &dst, int blockSize, int ksize, int bordertype = cv::BORDER_DEFAULT) +.. ocv:function:: void ocl::cornerMinEigenVal(const oclMat &src, oclMat &dst, int blockSize, int ksize, int bordertype = cv::BORDER_DEFAULT) :param src: Source image. Only CV_8UC1 and CV_32FC1 images are supported now. @@ -45,7 +45,7 @@ ocl::calcHist ------------------ Returns void -.. ocv:function:: void calcHist(const oclMat &mat_src, oclMat &mat_hist) +.. ocv:function:: void ocl::calcHist(const oclMat &mat_src, oclMat &mat_hist) :param src: Source arrays. They all should have the same depth, CV 8U, and the same size. Each of them can have an arbitrary number of channels. @@ -57,7 +57,7 @@ ocl::remap ------------------ Returns void -.. ocv:function:: void remap(const oclMat &src, oclMat &dst, oclMat &map1, oclMat &map2, int interpolation, int bordertype, const Scalar &value = Scalar()) +.. ocv:function:: void ocl::remap(const oclMat &src, oclMat &dst, oclMat &map1, oclMat &map2, int interpolation, int bordertype, const Scalar &value = Scalar()) :param src: Source image. Only CV_8UC1 and CV_32FC1 images are supported now. @@ -79,7 +79,7 @@ ocl::resize ------------------ Returns void -.. ocv:function:: void resize(const oclMat &src, oclMat &dst, Size dsize, double fx = 0, double fy = 0, int interpolation = INTER_LINEAR) +.. ocv:function:: void ocl::resize(const oclMat &src, oclMat &dst, Size dsize, double fx = 0, double fy = 0, int interpolation = INTER_LINEAR) :param src: Source image. @@ -99,7 +99,7 @@ ocl::warpAffine ------------------ Returns void -.. ocv:function:: void warpAffine(const oclMat &src, oclMat &dst, const Mat &M, Size dsize, int flags = INTER_LINEAR) +.. ocv:function:: void ocl::warpAffine(const oclMat &src, oclMat &dst, const Mat &M, Size dsize, int flags = INTER_LINEAR) :param src: Source image. @@ -117,7 +117,7 @@ ocl::warpPerspective --------------------- Returns void -.. ocv:function:: void warpPerspective(const oclMat &src, oclMat &dst, const Mat &M, Size dsize, int flags = INTER_LINEAR) +.. ocv:function:: void ocl::warpPerspective(const oclMat &src, oclMat &dst, const Mat &M, Size dsize, int flags = INTER_LINEAR) :param src: Source image. @@ -135,7 +135,7 @@ ocl::cvtColor ------------------ Returns void -.. ocv:function:: void cvtColor(const oclMat &src, oclMat &dst, int code , int dcn = 0) +.. ocv:function:: void ocl::cvtColor(const oclMat &src, oclMat &dst, int code , int dcn = 0) :param src: Source image. @@ -151,7 +151,7 @@ ocl::threshold ------------------ Returns Threshold value -.. ocv:function:: double threshold(const oclMat &src, oclMat &dst, double thresh, double maxVal, int type = THRESH_TRUNC) +.. ocv:function:: double ocl::threshold(const oclMat &src, oclMat &dst, double thresh, double maxVal, int type = THRESH_TRUNC) :param src: The source array @@ -169,7 +169,7 @@ ocl::buildWarpPlaneMaps ----------------------- Builds plane warping maps. -.. ocv:function:: void ocl::buildWarpPlaneMaps(Size src_size, Rect dst_roi, const Mat& R, double f, double s, double dist, oclMat& map_x, oclMat& map_y) +.. ocv:function:: void ocl::buildWarpPlaneMaps( Size src_size, Rect dst_roi, const Mat& K, const Mat& R, const Mat& T, float scale, oclMat& map_x, oclMat& map_y ) @@ -177,7 +177,7 @@ ocl::buildWarpCylindricalMaps ----------------------------- Builds cylindrical warping maps. -.. ocv:function:: void ocl::buildWarpCylindricalMaps(Size src_size, Rect dst_roi, const Mat& R, double f, double s, oclMat& map_x, oclMat& map_y) +.. ocv:function:: void ocl::buildWarpCylindricalMaps( Size src_size, Rect dst_roi, const Mat& K, const Mat& R, float scale, oclMat& map_x, oclMat& map_y ) @@ -186,14 +186,14 @@ ocl::buildWarpSphericalMaps --------------------------- Builds spherical warping maps. -.. ocv:function:: void ocl::buildWarpSphericalMaps(Size src_size, Rect dst_roi, const Mat& R, double f, double s, oclMat& map_x, oclMat& map_y) +.. ocv:function:: void ocl::buildWarpSphericalMaps( Size src_size, Rect dst_roi, const Mat& K, const Mat& R, float scale, oclMat& map_x, oclMat& map_y ) ocl::buildWarpPerspectiveMaps ----------------------------- Builds transformation maps for perspective transformation. -.. ocv:function:: void buildWarpAffineMaps(const Mat& M, bool inverse, Size dsize, oclMat& xmap, oclMat& ymap) +.. ocv:function:: void ocl::buildWarpAffineMaps(const Mat& M, bool inverse, Size dsize, oclMat& xmap, oclMat& ymap) :param M: *3x3* transformation matrix. @@ -212,7 +212,7 @@ ocl::buildWarpAffineMaps ------------------------ Builds transformation maps for affine transformation. -.. ocv:function:: void buildWarpAffineMaps(const Mat& M, bool inverse, Size dsize, oclMat& xmap, oclMat& ymap) +.. ocv:function:: void ocl::buildWarpAffineMaps(const Mat& M, bool inverse, Size dsize, oclMat& xmap, oclMat& ymap) :param M: *2x3* transformation matrix. diff --git a/modules/ocl/doc/matrix_reductions.rst b/modules/ocl/doc/matrix_reductions.rst index 6eb889a03..69b27eb65 100644 --- a/modules/ocl/doc/matrix_reductions.rst +++ b/modules/ocl/doc/matrix_reductions.rst @@ -7,7 +7,7 @@ ocl::countNonZero ------------------ Returns the number of non-zero elements in src -.. ocv:function:: int countNonZero(const oclMat &src) +.. ocv:function:: int ocl::countNonZero(const oclMat &src) :param src: Single-channel array @@ -17,7 +17,7 @@ ocl::minMax ------------------ Returns void -.. ocv:function:: void minMax(const oclMat &src, double *minVal, double *maxVal = 0, const oclMat &mask = oclMat()) +.. ocv:function:: void ocl::minMax(const oclMat &src, double *minVal, double *maxVal = 0, const oclMat &mask = oclMat()) :param src: Single-channel array @@ -33,7 +33,7 @@ ocl::minMaxLoc ------------------ Returns void -.. ocv:function:: void minMaxLoc(const oclMat &src, double *minVal, double *maxVal = 0, Point *minLoc = 0, Point *maxLoc = 0,const oclMat &mask = oclMat()) +.. ocv:function:: void ocl::minMaxLoc(const oclMat &src, double *minVal, double *maxVal = 0, Point *minLoc = 0, Point *maxLoc = 0,const oclMat &mask = oclMat()) :param src: Single-channel array @@ -53,7 +53,7 @@ ocl::Sum ------------------ Returns the sum of matrix elements for each channel -.. ocv:function:: Scalar sum(const oclMat &m) +.. ocv:function:: Scalar ocl::sum(const oclMat &m) :param m: The Source image of all depth @@ -63,7 +63,7 @@ ocl::sqrSum ------------------ Returns the squared sum of matrix elements for each channel -.. ocv:function:: Scalar sqrSum(const oclMat &m) +.. ocv:function:: Scalar ocl::sqrSum(const oclMat &m) :param m: The Source image of all depth diff --git a/modules/ocl/doc/object_detection.rst b/modules/ocl/doc/object_detection.rst index cbbcd78d1..6cd3a12ac 100644 --- a/modules/ocl/doc/object_detection.rst +++ b/modules/ocl/doc/object_detection.rst @@ -3,12 +3,13 @@ Object Detection .. highlight:: cpp -ocl::oclCascadeClassifier +ocl::OclCascadeClassifier ------------------------- +.. ocv:class:: ocl::OclCascadeClassifier : public CascadeClassifier Cascade classifier class used for object detection. Supports HAAR cascade classifier in the form of cross link :: - class CV_EXPORTS OclCascadeClassifier : public cv::CascadeClassifier + class CV_EXPORTS OclCascadeClassifier : public CascadeClassifier { public: OclCascadeClassifier() {}; @@ -19,11 +20,11 @@ Cascade classifier class used for object detection. Supports HAAR cascade classi CvSize maxSize = cvSize(0, 0)); }; -ocl::oclCascadeClassifier::oclHaarDetectObjects +ocl::OclCascadeClassifier::oclHaarDetectObjects ------------------------------------------------------ Returns the detected objects by a list of rectangles -.. ocv:function:: CvSeq *OclCascadeClassifier::oclHaarDetectObjects(oclMat &gimg, CvMemStorage *storage, double scaleFactor,int minNeighbors, int flags, CvSize minSize = cvSize(0, 0), CvSize maxSize = cvSize(0, 0)) +.. ocv:function:: CvSeq* ocl::OclCascadeClassifier::oclHaarDetectObjects(oclMat &gimg, CvMemStorage *storage, double scaleFactor,int minNeighbors, int flags, CvSize minSize = cvSize(0, 0), CvSize maxSize = cvSize(0, 0)) :param image: Matrix of type CV_8U containing an image where objects should be detected. @@ -39,7 +40,7 @@ Detects objects of different sizes in the input image,only tested for face detec ocl::MatchTemplateBuf --------------------- -.. ocv:class:: ocl::MatchTemplateBuf +.. ocv:struct:: ocl::MatchTemplateBuf Class providing memory buffers for :ocv:func:`ocl::matchTemplate` function, plus it allows to adjust some specific parameters. :: diff --git a/modules/ocl/doc/operations_on_matrices.rst b/modules/ocl/doc/operations_on_matrices.rst index 27696ca13..145659b99 100644 --- a/modules/ocl/doc/operations_on_matrices.rst +++ b/modules/ocl/doc/operations_on_matrices.rst @@ -3,11 +3,11 @@ Operations on Matrics .. highlight:: cpp -ocl::convertTo ------------------- +ocl::oclMat::convertTo +---------------------- Returns void -.. ocv:function:: void convertTo( oclMat &m, int rtype, double alpha = 1, double beta = 0 ) const +.. ocv:function:: void ocl::oclMat::convertTo( oclMat &m, int rtype, double alpha = 1, double beta = 0 ) const :param m: The destination matrix. If it does not have a proper size or type before the operation, it will be reallocated @@ -19,11 +19,11 @@ Returns void The method converts source pixel values to the target datatype. saturate cast is applied in the end to avoid possible overflows. Supports CV_8UC1, CV_8UC4, CV_32SC1, CV_32SC4, CV_32FC1, CV_32FC4. -ocl::copyTo ------------------- +ocl::oclMat::copyTo +------------------- Returns void -.. ocv:function:: void copyTo( oclMat &m, const oclMat &mask ) const +.. ocv:function:: void ocl::oclMat::copyTo( oclMat &m, const oclMat &mask ) const :param m: The destination matrix. If it does not have a proper size or type before the operation, it will be reallocated @@ -31,11 +31,11 @@ Returns void Copies the matrix to another one. Supports CV_8UC1, CV_8UC4, CV_32SC1, CV_32SC4, CV_32FC1, CV_32FC4 -ocl::setTo +ocl::oclMat::setTo ------------------ Returns oclMat -.. ocv:function:: oclMat &setTo(const Scalar &s, const oclMat &mask = oclMat()) +.. ocv:function:: oclMat& ocl::oclMat::setTo(const Scalar &s, const oclMat &mask = oclMat()) :param s: Assigned scalar, which is converted to the actual array type @@ -47,15 +47,16 @@ ocl::absdiff ------------------ Returns void -.. ocv:function:: void absdiff(const oclMat &a, const oclMat &b, oclMat &c) +.. ocv:function:: void ocl::absdiff( const oclMat& a, const oclMat& b, oclMat& c ) + +.. ocv:function:: void ocl::absdiff( const oclMat& a, const Scalar& s, oclMat& c ) -.. ocv:function:: void absdiff(const oclMat &a, const Scalar& sc, oclMat &c) :param a: The first input array :param b: The second input array, must be the same size and same type as a - :param sc: Scalar, the second input parameter + :param s: Scalar, the second input parameter :param c: The destination array, it will have the same size and same type as a @@ -65,17 +66,19 @@ ocl::add ------------------ Returns void -.. ocv:function:: void add(const oclMat &src1, const oclMat &src2, oclMat &dst, const oclMat& mask=oclMat()) +.. ocv:function:: void ocl::add( const oclMat & a, const oclMat & b, oclMat & c ) -.. ocv:function:: void add(const oclMat &src1, const Scalar &sc, oclMat &dst, const oclMat& mask=oclMat()) +.. ocv:function:: void ocl::add( const oclMat & a, const oclMat & b, oclMat & c, const oclMat & mask ) - :param src1: The first input array +.. ocv:function:: void ocl::add( const oclMat & a, const Scalar & sc, oclMat & c, const oclMat & mask=oclMat() ) - :param src2: The second input array, must be the same size and same type as src1 + :param a: The first input array + + :param b: The second input array, must be the same size and same type as src1 :param sc: Scalar, the second input parameter - :param dst: The destination array, it will have the same size and same type as src1 + :param c: The destination array, it will have the same size and same type as src1 :param mask: he optional operation mask, 8-bit single channel array; specifies elements of the destination array to be changed @@ -85,17 +88,22 @@ ocl::subtract ------------------ Returns void -.. ocv:function:: void subtract(const oclMat &src1, const oclMat &src2, oclMat &dst, const oclMat& mask=oclMat()) +.. ocv:function:: void ocl::subtract( const oclMat& a, const oclMat& b, oclMat& c ) -.. ocv:function:: void subtract(const oclMat &src1, const Scalar &sc, oclMat &dst, const oclMat& mask=oclMat()) +.. ocv:function:: void ocl::subtract( const oclMat& a, const oclMat& b, oclMat& c, const oclMat& mask ) - :param src1: The first input array +.. ocv:function:: void ocl::subtract( const oclMat& a, const Scalar& sc, oclMat& c, const oclMat& mask=oclMat() ) - :param src2: The second input array, must be the same size and same type as src1 +.. ocv:function:: void ocl::subtract( const Scalar& sc, const oclMat& a, oclMat& c, const oclMat& mask=oclMat() ) + + + :param a: The first input array + + :param b: The second input array, must be the same size and same type as src1 :param sc: Scalar, the second input parameter - :param dst: The destination array, it will have the same size and same type as src1 + :param c: The destination array, it will have the same size and same type as src1 :param mask: he optional operation mask, 8-bit single channel array; specifies elements of the destination array to be changed @@ -105,13 +113,13 @@ ocl::multiply ------------------ Returns void -.. ocv:function:: void multiply(const oclMat &src1, const oclMat &src2, oclMat &dst, double scale = 1) +.. ocv:function:: void ocl::multiply( const oclMat& a, const oclMat& b, oclMat& c, double scale=1 ) - :param src1: The first input array + :param a: The first input array - :param src2: The second input array, must be the same size and same type as src1 + :param b: The second input array, must be the same size and same type as src1 - :param dst: The destination array, it will have the same size and same type as src1 + :param c: The destination array, it will have the same size and same type as src1 :param scale: must be 1 now @@ -121,13 +129,15 @@ ocl::divide ------------------ Returns void -.. ocv:function:: void divide(const oclMat &src1, const oclMat &src2, oclMat &dst, double scale = 1) +.. ocv:function:: void ocl::divide( const oclMat& a, const oclMat& b, oclMat& c, double scale=1 ) - :param src1: The first input array +.. ocv:function:: void ocl::divide( double scale, const oclMat& b, oclMat& c ) - :param src2: The second input array, must be the same size and same type as src1 + :param a: The first input array - :param dst: The destination array, it will have the same size and same type as src1 + :param b: The second input array, must be the same size and same type as src1 + + :param c: The destination array, it will have the same size and same type as src1 :param scale: must be 1 now @@ -137,15 +147,15 @@ ocl::bitwise_and ------------------ Returns void -.. ocv:function:: void bitwise_and(const oclMat &src1, const oclMat &src2, oclMat &dst, const oclMat& mask=oclMat()) +.. ocv:function:: void ocl::bitwise_and( const oclMat& src1, const oclMat& src2, oclMat& dst, const oclMat& mask=oclMat() ) -.. ocv:function:: void bitwise_and(const oclMat &src1, const Scalar &sc, oclMat &dst, const oclMat& mask=oclMat()) +.. ocv:function:: void ocl::bitwise_and( const oclMat& src1, const Scalar& s, oclMat& dst, const oclMat& mask=oclMat() ) :param src1: The first input array :param src2: The second input array, must be the same size and same type as src1 - :param sc: Scalar, the second input parameter + :param s: Scalar, the second input parameter :param dst: The destination array, it will have the same size and same type as src1 @@ -157,15 +167,15 @@ ocl::bitwise_or ------------------ Returns void -.. ocv:function:: void bitwise_or(const oclMat &src1, const oclMat &src2, oclMat &dst, const oclMat& mask=oclMat()) +.. ocv:function:: void ocl::bitwise_or( const oclMat& src1, const oclMat& src2, oclMat& dst, const oclMat& mask=oclMat() ) -.. ocv:function:: void bitwise_or(const oclMat &src1, const Scalar &sc, oclMat &dst, const oclMat& mask=oclMat()) +.. ocv:function:: void ocl::bitwise_or( const oclMat& src1, const Scalar& s, oclMat& dst, const oclMat& mask=oclMat() ) :param src1: The first input array :param src2: The second input array, must be the same size and same type as src1 - :param sc: Scalar, the second input parameter + :param s: Scalar, the second input parameter :param dst: The destination array, it will have the same size and same type as src1 @@ -177,9 +187,9 @@ ocl::bitwise_xor ------------------ Returns void -.. ocv:function:: void bitwise_xor(const oclMat &src1, const oclMat &src2, oclMat &dst, const oclMat& mask=oclMat()) +.. ocv:function:: void ocl::bitwise_xor( const oclMat& src1, const oclMat& src2, oclMat& dst, const oclMat& mask=oclMat() ) -.. ocv:function:: void bitwise_xor(const oclMat &src1, const Scalar &sc, oclMat &dst, const oclMat& mask=oclMat()) +.. ocv:function:: void ocl::bitwise_xor( const oclMat& src1, const Scalar& s, oclMat& dst, const oclMat& mask=oclMat() ) :param src1: The first input array @@ -197,7 +207,7 @@ ocl::bitwise_not ------------------ Returns void -.. ocv:function:: void bitwise_not(const oclMat &src, oclMat &dst) +.. ocv:function:: void ocl::bitwise_not(const oclMat &src, oclMat &dst) :param src: The input array @@ -209,7 +219,7 @@ ocl::cartToPolar ------------------ Returns void -.. ocv:function:: void cartToPolar(const oclMat &x, const oclMat &y, oclMat &magnitude, oclMat &angle, bool angleInDegrees = false) +.. ocv:function:: void ocl::cartToPolar(const oclMat &x, const oclMat &y, oclMat &magnitude, oclMat &angle, bool angleInDegrees = false) :param x: The array of x-coordinates; must be single-precision or double-precision floating-point array @@ -227,7 +237,7 @@ ocl::polarToCart ------------------ Returns void -.. ocv:function:: void polarToCart(const oclMat &magnitude, const oclMat &angle, oclMat &x, oclMat &y, bool angleInDegrees = false) +.. ocv:function:: void ocl::polarToCart(const oclMat &magnitude, const oclMat &angle, oclMat &x, oclMat &y, bool angleInDegrees = false) :param magnitude: The source floating-point array of magnitudes of 2D vectors. It can be an empty matrix (=Mat()) - in this case the function assumes that all the magnitudes are =1. If it's not empty, it must have the same size and same type as angle @@ -245,7 +255,7 @@ ocl::compare ------------------ Returns void -.. ocv:function:: void compare(const oclMat &a, const oclMat &b, oclMat &c, int cmpop) +.. ocv:function:: void ocl::compare(const oclMat &a, const oclMat &b, oclMat &c, int cmpop) :param a: The first source array @@ -261,7 +271,7 @@ ocl::exp ------------------ Returns void -.. ocv:function:: void exp(const oclMat &a, oclMat &b) +.. ocv:function:: void ocl::exp(const oclMat &a, oclMat &b) :param a: The first source array @@ -273,7 +283,7 @@ ocl::log ------------------ Returns void -.. ocv:function:: void log(const oclMat &a, oclMat &b) +.. ocv:function:: void ocl::log(const oclMat &a, oclMat &b) :param a: The first source array @@ -285,7 +295,7 @@ ocl::LUT ------------------ Returns void -.. ocv:function:: void LUT(const oclMat &src, const oclMat &lut, oclMat &dst) +.. ocv:function:: void ocl::LUT(const oclMat &src, const oclMat &lut, oclMat &dst) :param src: Source array of 8-bit elements @@ -299,7 +309,7 @@ ocl::magnitude ------------------ Returns void -.. ocv:function:: void magnitude(const oclMat &x, const oclMat &y, oclMat &magnitude) +.. ocv:function:: void ocl::magnitude(const oclMat &x, const oclMat &y, oclMat &magnitude) :param x: The floating-point array of x-coordinates of the vectors @@ -313,11 +323,11 @@ ocl::flip ------------------ Returns void -.. ocv:function:: void flip(const oclMat &src, oclMat &dst, int flipCode) +.. ocv:function:: void ocl::flip( const oclMat& a, oclMat& b, int flipCode ) - :param src: Source image. + :param a: Source image. - :param dst: Destination image + :param b: Destination image :param flipCode: Specifies how to flip the array: 0 means flipping around the x-axis, positive (e.g., 1) means flipping around y-axis, and negative (e.g., -1) means flipping around both axes. @@ -327,7 +337,7 @@ ocl::meanStdDev ------------------ Returns void -.. ocv:function:: void meanStdDev(const oclMat &mtx, Scalar &mean, Scalar &stddev) +.. ocv:function:: void ocl::meanStdDev(const oclMat &mtx, Scalar &mean, Scalar &stddev) :param mtx: Source image. @@ -341,7 +351,7 @@ ocl::merge ------------------ Returns void -.. ocv:function:: void merge(const vector &src, oclMat &dst) +.. ocv:function:: void ocl::merge(const vector &src, oclMat &dst) :param src: The source array or vector of the single-channel matrices to be merged. All the matrices in src must have the same size and the same type @@ -353,7 +363,7 @@ ocl::split ------------------ Returns void -.. ocv:function:: void split(const oclMat &src, vector &dst) +.. ocv:function:: void ocl::split(const oclMat &src, vector &dst) :param src: The source multi-channel array @@ -365,9 +375,9 @@ ocl::norm ------------------ Returns the calculated norm -.. ocv:function:: double norm(const oclMat &src1, int normType = NORM_L2) +.. ocv:function:: double ocl::norm(const oclMat &src1, int normType = NORM_L2) -.. ocv:function:: double norm(const oclMat &src1, const oclMat &src2, int normType = NORM_L2) +.. ocv:function:: double ocl::norm(const oclMat &src1, const oclMat &src2, int normType = NORM_L2) :param src1: The first source array @@ -381,7 +391,7 @@ ocl::phase ------------------ Returns void -.. ocv:function:: void phase(const oclMat &x, const oclMat &y, oclMat &angle, bool angleInDegrees = false) +.. ocv:function:: void ocl::phase(const oclMat &x, const oclMat &y, oclMat &angle, bool angleInDegrees = false) :param x: The source floating-point array of x-coordinates of 2D vectors @@ -397,7 +407,7 @@ ocl::pow ------------------ Returns void -.. ocv:function:: void pow(const oclMat &x, double p, oclMat &y) +.. ocv:function:: void ocl::pow(const oclMat &x, double p, oclMat &y) :param x: The source array @@ -411,7 +421,7 @@ ocl::transpose ------------------ Returns void -.. ocv:function:: void transpose(const oclMat &src, oclMat &dst) +.. ocv:function:: void ocl::transpose(const oclMat &src, oclMat &dst) :param src: The source array @@ -424,7 +434,7 @@ ocl::dft ------------ Performs a forward or inverse discrete Fourier transform (1D or 2D) of the floating point matrix. -.. ocv:function:: void ocl::dft(const oclMat& src, oclMat& dst, Size dft_size, int flags=0) +.. ocv:function:: void ocl::dft( const oclMat& src, oclMat& dst, Size dft_size=Size(0, 0), int flags=0 ) :param src: Source matrix (real or complex). @@ -452,7 +462,7 @@ ocl::gemm ------------------ Performs generalized matrix multiplication. -.. ocv:function:: void gemm(const oclMat& src1, const oclMat& src2, double alpha, const oclMat& src3, double beta, oclMat& dst, int flags = 0) +.. ocv:function:: void ocl::gemm(const oclMat& src1, const oclMat& src2, double alpha, const oclMat& src3, double beta, oclMat& dst, int flags = 0) :param src1: First multiplied input matrix that should be ``CV_32FC1`` type. diff --git a/modules/ocl/doc/structures_and_utility_functions.rst b/modules/ocl/doc/structures_and_utility_functions.rst index df19a3c1d..32aa8b9ea 100644 --- a/modules/ocl/doc/structures_and_utility_functions.rst +++ b/modules/ocl/doc/structures_and_utility_functions.rst @@ -35,7 +35,7 @@ ocl::setBinpath ------------------ Returns void -.. ocv:function:: void setBinpath(const char *path) +.. ocv:function:: void ocl::setBinpath(const char *path) :param path: the path of OpenCL kernel binaries @@ -45,7 +45,7 @@ ocl::getoclContext ------------------ Returns the pointer to the opencl context -.. ocv:function:: void *getoclContext() +.. ocv:function:: void* ocl::getoclContext() Thefunction are used to get opencl context so that opencv can interactive with other opencl program. @@ -53,6 +53,6 @@ ocl::getoclCommandQueue -------------------------- Returns the pointer to the opencl command queue -.. ocv:function:: void *getoclCommandQueue() +.. ocv:function:: void* ocl::getoclCommandQueue() Thefunction are used to get opencl command queue so that opencv can interactive with other opencl program. \ No newline at end of file diff --git a/modules/ocl/include/opencv2/ocl/ocl.hpp b/modules/ocl/include/opencv2/ocl/ocl.hpp index 419b05b63..4a56cff20 100644 --- a/modules/ocl/include/opencv2/ocl/ocl.hpp +++ b/modules/ocl/include/opencv2/ocl/ocl.hpp @@ -95,9 +95,9 @@ namespace cv //other opencl program - CV_EXPORTS void *getoclContext(); + CV_EXPORTS void* getoclContext(); - CV_EXPORTS void *getoclCommandQueue(); + CV_EXPORTS void* getoclCommandQueue(); //////////////////////////////// Error handling //////////////////////// CV_EXPORTS void error(const char *error_string, const char *file, const int line, const char *func); @@ -191,10 +191,10 @@ namespace cv //! sets every oclMatrix element to s //It supports 8UC1 8UC4 32SC1 32SC4 32FC1 32FC4 - oclMat &operator = (const Scalar &s); + oclMat& operator = (const Scalar &s); //! sets some of the oclMatrix elements to s, according to the mask //It supports 8UC1 8UC4 32SC1 32SC4 32FC1 32FC4 - oclMat &setTo(const Scalar &s, const oclMat &mask = oclMat()); + oclMat& setTo(const Scalar &s, const oclMat &mask = oclMat()); //! creates alternative oclMatrix header for the same data, with different // number of channels and/or different number of rows. see cvReshape. oclMat reshape(int cn, int rows = 0) const; @@ -213,7 +213,7 @@ namespace cv //! locates oclMatrix header within a parent oclMatrix. See below void locateROI( Size &wholeSize, Point &ofs ) const; //! moves/resizes the current oclMatrix ROI inside the parent oclMatrix. - oclMat &adjustROI( int dtop, int dbottom, int dleft, int dright ); + oclMat& adjustROI( int dtop, int dbottom, int dleft, int dright ); //! extracts a rectangular sub-oclMatrix // (this is a generalized form of row, rowRange etc.) oclMat operator()( Range rowRange, Range colRange ) const; @@ -249,7 +249,7 @@ namespace cv bool empty() const; //! returns pointer to y-th row - uchar *ptr(int y = 0); + uchar* ptr(int y = 0); const uchar *ptr(int y = 0) const; //! template version of the above method @@ -347,7 +347,7 @@ namespace cv //! transposes the matrix // supports CV_8UC1, 8UC4, 8SC4, 16UC2, 16SC2, 32SC1 and 32FC1.(the same as cuda) - CV_EXPORTS void transpose(const oclMat &src1, oclMat &dst); + CV_EXPORTS void transpose(const oclMat &src, oclMat &dst); //! computes element-wise absolute difference of two arrays (c = abs(a - b)) // supports all types except CV_8SC1,CV_8SC2,CV8SC3 and CV_8SC4 @@ -407,7 +407,7 @@ namespace cv CV_EXPORTS void equalizeHist(const oclMat &mat_src, oclMat &mat_dst); //! bilateralFilter // supports 8UC1 8UC4 - CV_EXPORTS void bilateralFilter(const oclMat &, oclMat &, int , double, double, int); + CV_EXPORTS void bilateralFilter(const oclMat& src, oclMat& dst, int d, double sigmaColor, double sigmaSpave, int borderType=BORDER_DEFAULT); //! computes exponent of each matrix element (b = e**a) // supports only CV_32FC1 type CV_EXPORTS void exp(const oclMat &a, oclMat &b); @@ -719,7 +719,7 @@ namespace cv OclCascadeClassifier() {}; ~OclCascadeClassifier() {}; - CvSeq *oclHaarDetectObjects(oclMat &gimg, CvMemStorage *storage, double scaleFactor, + CvSeq* oclHaarDetectObjects(oclMat &gimg, CvMemStorage *storage, double scaleFactor, int minNeighbors, int flags, CvSize minSize = cvSize(0, 0), CvSize maxSize = cvSize(0, 0)); }; @@ -729,7 +729,7 @@ namespace cv CV_EXPORTS void pyrDown(const oclMat &src, oclMat &dst); //! upsamples the source image and then smoothes it - CV_EXPORTS void pyrUp(const cv::ocl::oclMat &src, cv::ocl::oclMat &dst); + CV_EXPORTS void pyrUp(const oclMat &src, oclMat &dst); //! performs linear blending of two images //! to avoid accuracy errors sum of weigths shouldn't be very close to zero @@ -1705,11 +1705,11 @@ namespace cv }; //////////////// build warping maps //////////////////// //! builds plane warping maps - CV_EXPORTS void buildWarpPlaneMaps(Size, Rect, const Mat &, const Mat &, const Mat &, float, oclMat &, oclMat &); + CV_EXPORTS void buildWarpPlaneMaps(Size src_size, Rect dst_roi, const Mat &K, const Mat &R, const Mat &T, float scale, oclMat &map_x, oclMat &map_y); //! builds cylindrical warping maps - CV_EXPORTS void buildWarpCylindricalMaps(Size, Rect, const Mat &, const Mat &, float, oclMat &, oclMat &); + CV_EXPORTS void buildWarpCylindricalMaps(Size src_size, Rect dst_roi, const Mat &K, const Mat &R, float scale, oclMat &map_x, oclMat &map_y); //! builds spherical warping maps - CV_EXPORTS void buildWarpSphericalMaps(Size, Rect, const Mat &, const Mat &, float, oclMat &, oclMat &); + CV_EXPORTS void buildWarpSphericalMaps(Size src_size, Rect dst_roi, const Mat &K, const Mat &R, float scale, oclMat &map_x, oclMat &map_y); //! builds Affine warping maps CV_EXPORTS void buildWarpAffineMaps(const Mat &M, bool inverse, Size dsize, oclMat &xmap, oclMat &ymap); diff --git a/modules/python/src2/hdr_parser.py b/modules/python/src2/hdr_parser.py index 8335b0c52..4c81b04ff 100755 --- a/modules/python/src2/hdr_parser.py +++ b/modules/python/src2/hdr_parser.py @@ -575,6 +575,8 @@ class CppHeaderParser(object): """ if not self.block_stack: return name + if name.startswith("cv."): + return name n = "" for b in self.block_stack: block_type, block_name = b[self.BLOCK_TYPE], b[self.BLOCK_NAME] From c0411caef4fb9308fc5f9ba88a99b3ebbd8a4e61 Mon Sep 17 00:00:00 2001 From: Vsevolod Glumov Date: Fri, 28 Dec 2012 15:03:20 +0400 Subject: [PATCH 20/34] Fixed a bunch of minor issues in 'dev_with_OCV_on_Android.rst'. --- .../dev_with_OCV_on_Android.rst | 245 +++++++++++------- 1 file changed, 145 insertions(+), 100 deletions(-) diff --git a/doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.rst b/doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.rst index ba82a8a01..9a96307ab 100644 --- a/doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.rst +++ b/doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.rst @@ -1,13 +1,13 @@ .. _dev_with_OCV_on_Android: - -Android development with OpenCV +Android Development with OpenCV ******************************* -This tutorial is created to help you use OpenCV library within your Android project. +This tutorial has been created to help you use OpenCV library within your Android project. -This guide was written with Windows 7 in mind, though it should work with any other OS supported by OpenCV4Android SDK. +This guide was written with Windows 7 in mind, though it should work with any other OS supported by +OpenCV4Android SDK. This tutorial assumes you have the following installed and configured: @@ -23,41 +23,57 @@ This tutorial assumes you have the following installed and configured: If you need help with anything of the above, you may refer to our :ref:`android_dev_intro` guide. -This tutorial also assumes you have OpenCV4Android SDK already installed on your development machine and OpenCV Manager on your testing device correspondingly. If you need help with any of these, you may consult our :ref:`O4A_SDK` tutorial. +This tutorial also assumes you have OpenCV4Android SDK already installed on your development +machine and OpenCV Manager on your testing device correspondingly. If you need help with any of +these, you may consult our :ref:`O4A_SDK` tutorial. -If you encounter any error after thoroughly following these steps, feel free to contact us via `OpenCV4Android `_ discussion group or OpenCV `Q&A forum `_ . We'll do our best to help you out. +If you encounter any error after thoroughly following these steps, feel free to contact us via +`OpenCV4Android `_ discussion group or OpenCV +`Q&A forum `_ . We'll do our best to help you out. -Using OpenCV library within your Android project + +Using OpenCV Library Within Your Android Project ================================================ -In this section we will explain how to make some existing project to use OpenCV. -Starting with 2.4.2 release for Android, *OpenCV Manager* is used to provide apps with the best available version of OpenCV. -You can get more information here: :ref:`Android_OpenCV_Manager` and in these `slides `_. +In this section we will explain how to make some existing project to use OpenCV. +Starting with 2.4.2 release for Android, *OpenCV Manager* is used to provide apps with the best +available version of OpenCV. +You can get more information here: :ref:`Android_OpenCV_Manager` and in these +`slides `_. + Java ---- -Application development with async initialization + +Application Development with Async Initialization ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Using async initialization is a **recommended** way for application development. It uses the OpenCV Manager to access OpenCV libraries externally installed in the target system. +Using async initialization is a **recommended** way for application development. It uses the OpenCV +Manager to access OpenCV libraries externally installed in the target system. -#. Add OpenCV library project to your workspace. Use menu :guilabel:`File -> Import -> Existing project in your workspace`, - press :guilabel:`Browse` button and locate OpenCV4Android SDK (:file:`OpenCV-2.4.3-android-sdk/sdk`). +#. Add OpenCV library project to your workspace. Use menu + :guilabel:`File -> Import -> Existing project in your workspace`. + + Press :guilabel:`Browse` button and locate OpenCV4Android SDK + (:file:`OpenCV-2.4.3-android-sdk/sdk`). .. image:: images/eclipse_opencv_dependency0.png :alt: Add dependency from OpenCV library :align: center -#. In application project add a reference to the OpenCV Java SDK in :guilabel:`Project -> Properties -> Android -> Library -> Add` select ``OpenCV Library - 2.4.3``. +#. In application project add a reference to the OpenCV Java SDK in + :guilabel:`Project -> Properties -> Android -> Library -> Add` select ``OpenCV Library - 2.4.3``. .. image:: images/eclipse_opencv_dependency1.png :alt: Add dependency from OpenCV library :align: center -In most cases OpenCV Manager may be installed automatically from Google Play. For such case, when Google Play is not available, i.e. emulator, developer board, etc, you can -install it manually using adb tool. See :ref:`manager_selection` for details. +In most cases OpenCV Manager may be installed automatically from Google Play. For the case, when +Google Play is not available, i.e. emulator, developer board, etc, you can install it manually +using adb tool. See :ref:`manager_selection` for details. -There is a very base code snippet implementing the async initialization. It shows basic principles. See the "15-puzzle" OpenCV sample for details. +There is a very base code snippet implementing the async initialization. It shows basic principles. +See the "15-puzzle" OpenCV sample for details. .. code-block:: java :linenos: @@ -97,35 +113,48 @@ There is a very base code snippet implementing the async initialization. It show } } -It this case application works with OpenCV Manager in asynchronous fashion. ``OnManagerConnected`` callback will be called in UI thread, when initialization finishes. -Please note, that it is not allowed to use OpenCV calls or load OpenCV-dependent native libs before invoking this callback. -Load your own native libraries that depend on OpenCV after the successful OpenCV initialization. -Default BaseLoaderCallback implementation treat application context as Activity and calls Activity.finish() method to exit in case of initialization failure. -To override this behavior you need to override finish() method of BaseLoaderCallback class and implement your own finalization method. +It this case application works with OpenCV Manager in asynchronous fashion. ``OnManagerConnected`` +callback will be called in UI thread, when initialization finishes. Please note, that it is not +allowed to use OpenCV calls or load OpenCV-dependent native libs before invoking this callback. +Load your own native libraries that depend on OpenCV after the successful OpenCV initialization. +Default ``BaseLoaderCallback`` implementation treat application context as Activity and calls +``Activity.finish()`` method to exit in case of initialization failure. To override this behavior +you need to override ``finish()`` method of ``BaseLoaderCallback`` class and implement your own +finalization method. -Application development with static initialization + +Application Development with Static Initialization ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -According to this approach all OpenCV binaries are included into your application package. It is designed mostly for development purposes. -This approach is deprecated for the production code, release package is recommended to communicate with OpenCV Manager via the async initialization described above. +According to this approach all OpenCV binaries are included into your application package. It is +designed mostly for development purposes. This approach is deprecated for the production code, +release package is recommended to communicate with OpenCV Manager via the async initialization +described above. -#. Add the OpenCV library project to your workspace the same way as for the async initialization above. - Use menu :guilabel:`File -> Import -> Existing project in your workspace`, push :guilabel:`Browse` button and select OpenCV SDK path (:file:`OpenCV-2.4.3-android-sdk/sdk`). +#. Add the OpenCV library project to your workspace the same way as for the async initialization + above. Use menu :guilabel:`File -> Import -> Existing project in your workspace`, + press :guilabel:`Browse` button and select OpenCV SDK path + (:file:`OpenCV-2.4.3-android-sdk/sdk`). .. image:: images/eclipse_opencv_dependency0.png :alt: Add dependency from OpenCV library :align: center -#. In the application project add a reference to the OpenCV4Android SDK in :guilabel:`Project -> Properties -> Android -> Library -> Add` select ``OpenCV Library - 2.4.3``; +#. In the application project add a reference to the OpenCV4Android SDK in + :guilabel:`Project -> Properties -> Android -> Library -> Add` select ``OpenCV Library - 2.4.3``; .. image:: images/eclipse_opencv_dependency1.png :alt: Add dependency from OpenCV library :align: center -#. If your application project **doesn't have a JNI part**, just copy the corresponding OpenCV native libs from :file:`/sdk/native/libs/` to your project directory to folder :file:`libs/`. +#. If your application project **doesn't have a JNI part**, just copy the corresponding OpenCV + native libs from :file:`/sdk/native/libs/` to your + project directory to folder :file:`libs/`. - In case of the application project **with a JNI part**, instead of manual libraries copying you need to modify your ``Android.mk`` file: - add the following two code lines after the ``"include $(CLEAR_VARS)"`` and before ``"include path_to_OpenCV-2.4.3-android-sdk/sdk/native/jni/OpenCV.mk"`` + In case of the application project **with a JNI part**, instead of manual libraries copying you + need to modify your ``Android.mk`` file: + add the following two code lines after the ``"include $(CLEAR_VARS)"`` and before + ``"include path_to_OpenCV-2.4.3-android-sdk/sdk/native/jni/OpenCV.mk"`` .. code-block:: make :linenos: @@ -145,12 +174,14 @@ This approach is deprecated for the production code, release package is recommen OPENCV_INSTALL_MODULES:=on include ../../sdk/native/jni/OpenCV.mk - After that the OpenCV libraries will be copied to your application :file:`libs` folder during the JNI part build. + After that the OpenCV libraries will be copied to your application :file:`libs` folder during + the JNI build.v - Eclipse will automatically include all the libraries from the :file:`libs` folder to the application package (APK). + Eclipse will automatically include all the libraries from the :file:`libs` folder to the + application package (APK). -#. The last step of enabling OpenCV in your application is Java initialization code before call to OpenCV API. - It can be done, for example, in the static section of the ``Activity`` class: +#. The last step of enabling OpenCV in your application is Java initialization code before calling + OpenCV API. It can be done, for example, in the static section of the ``Activity`` class: .. code-block:: java :linenos: @@ -161,7 +192,8 @@ This approach is deprecated for the production code, release package is recommen } } - If you application includes other OpenCV-dependent native libraries you should load them **after** OpenCV initialization: + If you application includes other OpenCV-dependent native libraries you should load them + **after** OpenCV initialization: .. code-block:: java :linenos: @@ -175,39 +207,45 @@ This approach is deprecated for the production code, release package is recommen } } + Native/C++ ---------- -To build your own Android application, which uses OpenCV from native part, the following steps should be done: +To build your own Android application, using OpenCV as native part, the following steps should be +taken: -#. You can use an environment variable to specify the location of OpenCV package or just hardcode absolute or relative path in the :file:`jni/Android.mk` of your projects. +#. You can use an environment variable to specify the location of OpenCV package or just hardcode + absolute or relative path in the :file:`jni/Android.mk` of your projects. -#. The file :file:`jni/Android.mk` should be written for the current application using the common rules for this file. +#. The file :file:`jni/Android.mk` should be written for the current application using the common + rules for this file. - For detailed information see the Android NDK documentation from the Android NDK archive, in the file - :file:`/docs/ANDROID-MK.html` + For detailed information see the Android NDK documentation from the Android NDK archive, in the + file :file:`/docs/ANDROID-MK.html`. -#. The line +#. The following line: .. code-block:: make include C:\Work\OpenCV4Android\OpenCV-2.4.3-android-sdk\sdk\native\jni\OpenCV.mk - should be inserted into the :file:`jni/Android.mk` file **after** the line + Should be inserted into the :file:`jni/Android.mk` file **after** this line: .. code-block:: make include $(CLEAR_VARS) -#. Several variables can be used to customize OpenCV stuff, but you **don't need** to use them when your application uses the `async initialization` via the `OpenCV Manager` API. +#. Several variables can be used to customize OpenCV stuff, but you **don't need** to use them when + your application uses the `async initialization` via the `OpenCV Manager` API. - Note: these variables should be set **before** the ``"include .../OpenCV.mk"`` line: + .. note:: These variables should be set **before** the ``"include .../OpenCV.mk"`` line: - .. code-block:: make + .. code-block:: make - OPENCV_INSTALL_MODULES:=on + OPENCV_INSTALL_MODULES:=on - Copies necessary OpenCV dynamic libs to the project ``libs`` folder in order to include them into the APK. + Copies necessary OpenCV dynamic libs to the project ``libs`` folder in order to include them + into the APK. .. code-block:: make @@ -219,7 +257,8 @@ To build your own Android application, which uses OpenCV from native part, the f OPENCV_LIB_TYPE:=STATIC - Perform static link with OpenCV. By default dynamic link is used and the project JNI lib depends on ``libopencv_java.so``. + Perform static linking with OpenCV. By default dynamic link is used and the project JNI lib + depends on ``libopencv_java.so``. #. The file :file:`Application.mk` should exist and should contain lines: @@ -228,50 +267,56 @@ To build your own Android application, which uses OpenCV from native part, the f APP_STL := gnustl_static APP_CPPFLAGS := -frtti -fexceptions - Also the line like this one: + Also, the line like this one: .. code-block:: make APP_ABI := armeabi-v7a - should specify the application target platforms. + Should specify the application target platforms. - In some cases a linkage error (like ``"In function 'cv::toUtf16(std::basic_string<...>... undefined reference to 'mbstowcs'"``) happens - when building an application JNI library depending on OpenCV. - The following line in the :file:`Application.mk` usually fixes it: + In some cases a linkage error (like ``"In function 'cv::toUtf16(std::basic_string<...>... + undefined reference to 'mbstowcs'"``) happens when building an application JNI library, + depending on OpenCV. The following line in the :file:`Application.mk` usually fixes it: .. code-block:: make APP_PLATFORM := android-9 -#. Either use :ref:`manual ` ``ndk-build`` invocation or :ref:`setup Eclipse CDT Builder ` to build native JNI lib before Java part [re]build and APK creation. +#. Either use :ref:`manual ` ``ndk-build`` invocation or + :ref:`setup Eclipse CDT Builder ` to build native JNI lib before (re)building the Java + part and creating an APK. Hello OpenCV Sample =================== -Here are basic steps to guide you trough the process of creating a simple OpenCV-centric application. -It will be capable of accessing camera output, processing it and displaying the result. +Here are basic steps to guide you trough the process of creating a simple OpenCV-centric +application. It will be capable of accessing camera output, processing it and displaying the +result. -#. Open Eclipse IDE, create a new clean workspace, create a new Android project (*File -> New -> Android Project*). +#. Open Eclipse IDE, create a new clean workspace, create a new Android project + :menuselection:`File --> New --> Android Project`. -#. Set name, target, package and minSDKVersion accordingly. +#. Set name, target, package and ``minSDKVersion`` accordingly. -#. Create a new class (*File -> New -> Class*). Name it for example: *HelloOpenCVView*. +#. Create a new class :menuselection:`File -> New -> Class`. Name it for example: + *HelloOpenCVView*. .. image:: images/dev_OCV_new_class.png :alt: Add a new class. :align: center - * It should extend *SurfaceView* class. - * It also should implement *SurfaceHolder.Callback*, *Runnable*. + * It should extend ``SurfaceView`` class. + * It also should implement ``SurfaceHolder.Callback``, ``Runnable``. -#. Edit *HelloOpenCVView* class. +#. Edit ``HelloOpenCVView`` class. - * Add an *import* line for *android.content.context*. + * Add an ``import`` line for ``android.content.context``. - * Modify autogenerated stubs: *HelloOpenCVView*, *surfaceCreated*, *surfaceDestroyed* and *surfaceChanged*. + * Modify autogenerated stubs: ``HelloOpenCVView``, ``surfaceCreated``, ``surfaceDestroyed`` and + ``surfaceChanged``. .. code-block:: java :linenos: @@ -299,11 +344,9 @@ It will be capable of accessing camera output, processing it and displaying the cameraSetup(width, height); } - //... + * Add ``cameraOpen``, ``cameraRelease`` and ``cameraSetup`` voids as shown below. - * Add *cameraOpen*, *cameraRelease* and *cameraSetup* voids as shown below. - - * Also, don't forget to add the public void *run()* as follows: + * Also, don't forget to add the public void ``run()`` as follows: .. code-block:: java :linenos: @@ -324,40 +367,42 @@ It will be capable of accessing camera output, processing it and displaying the // TODO setup camera } -#. Create a new *Activity* (*New -> Other -> Android -> Android Activity*) and name it, for example: *HelloOpenCVActivity*. For this activity define *onCreate*, *onResume* and *onPause* voids. +#. Create a new ``Activity`` :menuselection:`New -> Other -> Android -> Android Activity` and name + it, for example: *HelloOpenCVActivity*. For this activity define ``onCreate``, ``onResume`` and + ``onPause`` voids. .. code-block:: java :linenos: - public void onCreate (Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - mView = new HelloOpenCVView(this); - setContentView (mView); - } + public void onCreate (Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mView = new HelloOpenCVView(this); + setContentView (mView); + } - protected void onPause() { - super.onPause(); - mView.cameraRelease(); - } + protected void onPause() { + super.onPause(); + mView.cameraRelease(); + } - protected void onResume() { - super.onResume(); - if( !mView.cameraOpen() ) { - // MessageBox and exit app - AlertDialog ad = new AlertDialog.Builder(this).create(); - ad.setCancelable(false); // This blocks the "BACK" button - ad.setMessage("Fatal error: can't open camera!"); - ad.setButton("OK", new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - finish(); - } - }); - ad.show(); - } - } + protected void onResume() { + super.onResume(); + if( !mView.cameraOpen() ) { + // MessageBox and exit app + AlertDialog ad = new AlertDialog.Builder(this).create(); + ad.setCancelable(false); // This blocks the "BACK" button + ad.setMessage("Fatal error: can't open camera!"); + ad.setButton("OK", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + finish(); + } + }); + ad.show(); + } + } -#. Add the following permissions to the AndroidManifest.xml file: +#. Add the following permissions to the :file:`AndroidManifest.xml` file: .. code-block:: xml :linenos: @@ -374,12 +419,12 @@ It will be capable of accessing camera output, processing it and displaying the :alt: Reference OpenCV library. :align: center -#. We now need some code to handle the camera. Update the *HelloOpenCVView* class as follows: +#. We now need some code to handle the camera. Update the ``HelloOpenCVView`` class as follows: .. code-block:: java :linenos: - private VideoCapture mCamera; + private VideoCapture mCamera; public boolean cameraOpen() { synchronized (this) { @@ -426,7 +471,7 @@ It will be capable of accessing camera output, processing it and displaying the } } -#. The last step would be to update the *run()* void in *HelloOpenCVView* class as follows: +#. The last step would be to update the ``run()`` void in ``HelloOpenCVView`` class as follows: .. code-block:: java :linenos: From e3317876455cdc4929a8c0da721a976a87f5544d Mon Sep 17 00:00:00 2001 From: Zifei Tong <5kilograms@gmail.com> Date: Thu, 27 Dec 2012 15:43:16 +0800 Subject: [PATCH 21/34] Fix race condition for Cascade Classifier when TBB enabled. --- modules/objdetect/src/cascadedetect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/objdetect/src/cascadedetect.cpp b/modules/objdetect/src/cascadedetect.cpp index ad3a73052..38c2e0a0b 100644 --- a/modules/objdetect/src/cascadedetect.cpp +++ b/modules/objdetect/src/cascadedetect.cpp @@ -992,9 +992,9 @@ public: { mtx->lock(); rectangles->push_back(Rect(cvRound(x*scalingFactor), cvRound(y*scalingFactor), winSize.width, winSize.height)); - mtx->unlock(); rejectLevels->push_back(-result); levelWeights->push_back(gypWeight); + mtx->unlock(); } } else if( result > 0 ) From 260bdc057cdc81da8b0b09869ac16754bd1d8fd6 Mon Sep 17 00:00:00 2001 From: Zifei Tong <5kilograms@gmail.com> Date: Fri, 28 Dec 2012 14:44:06 +0800 Subject: [PATCH 22/34] Changed parallel_for to parallel_for_ in haar.cpp --- modules/objdetect/src/haar.cpp | 51 +++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/modules/objdetect/src/haar.cpp b/modules/objdetect/src/haar.cpp index 96bc7603b..54133f5f3 100644 --- a/modules/objdetect/src/haar.cpp +++ b/modules/objdetect/src/haar.cpp @@ -1277,14 +1277,15 @@ cvRunHaarClassifierCascade( const CvHaarClassifierCascade* _cascade, namespace cv { -struct HaarDetectObjects_ScaleImage_Invoker +class HaarDetectObjects_ScaleImage_Invoker : public ParallelLoopBody { +public: HaarDetectObjects_ScaleImage_Invoker( const CvHaarClassifierCascade* _cascade, int _stripSize, double _factor, const Mat& _sum1, const Mat& _sqsum1, Mat* _norm1, - Mat* _mask1, Rect _equRect, ConcurrentRectVector& _vec, + Mat* _mask1, Rect _equRect, std::vector& _vec, std::vector& _levels, std::vector& _weights, - bool _outputLevels ) + bool _outputLevels, Mutex *_mtx ) { cascade = _cascade; stripSize = _stripSize; @@ -1297,13 +1298,14 @@ struct HaarDetectObjects_ScaleImage_Invoker vec = &_vec; rejectLevels = _outputLevels ? &_levels : 0; levelWeights = _outputLevels ? &_weights : 0; + mtx = _mtx; } - void operator()( const BlockedRange& range ) const + void operator()( const Range& range ) const { Size winSize0 = cascade->orig_window_size; Size winSize(cvRound(winSize0.width*factor), cvRound(winSize0.height*factor)); - int y1 = range.begin()*stripSize, y2 = min(range.end()*stripSize, sum1.rows - 1 - winSize0.height); + int y1 = range.start*stripSize, y2 = min(range.end*stripSize, sum1.rows - 1 - winSize0.height); if (y2 <= y1 || sum1.cols <= 1 + winSize0.width) return; @@ -1356,8 +1358,10 @@ struct HaarDetectObjects_ScaleImage_Invoker for( x = 0; x < ssz.width; x += ystep ) if( mask1row[x] != 0 ) { + mtx->lock(); vec->push_back(Rect(cvRound(x*factor), cvRound(y*factor), winSize.width, winSize.height)); + mtx->unlock(); if( --positive == 0 ) break; } @@ -1378,17 +1382,23 @@ struct HaarDetectObjects_ScaleImage_Invoker result = -1*cascade->count; if( cascade->count + result < 4 ) { + mtx->lock(); vec->push_back(Rect(cvRound(x*factor), cvRound(y*factor), winSize.width, winSize.height)); rejectLevels->push_back(-result); levelWeights->push_back(gypWeight); + mtx->unlock(); } } else { if( result > 0 ) + { + mtx->lock(); vec->push_back(Rect(cvRound(x*factor), cvRound(y*factor), winSize.width, winSize.height)); + mtx->unlock(); + } } } } @@ -1398,18 +1408,20 @@ struct HaarDetectObjects_ScaleImage_Invoker double factor; Mat sum1, sqsum1, *norm1, *mask1; Rect equRect; - ConcurrentRectVector* vec; + std::vector* vec; std::vector* rejectLevels; std::vector* levelWeights; + Mutex* mtx; }; -struct HaarDetectObjects_ScaleCascade_Invoker +class HaarDetectObjects_ScaleCascade_Invoker : public ParallelLoopBody { +public: HaarDetectObjects_ScaleCascade_Invoker( const CvHaarClassifierCascade* _cascade, Size _winsize, const Range& _xrange, double _ystep, size_t _sumstep, const int** _p, const int** _pq, - ConcurrentRectVector& _vec ) + std::vector& _vec, Mutex* _mtx ) { cascade = _cascade; winsize = _winsize; @@ -1418,11 +1430,12 @@ struct HaarDetectObjects_ScaleCascade_Invoker sumstep = _sumstep; p = _p; pq = _pq; vec = &_vec; + mtx = _mtx; } - void operator()( const BlockedRange& range ) const + void operator()( const Range& range ) const { - int iy, startY = range.begin(), endY = range.end(); + int iy, startY = range.start, endY = range.end; const int *p0 = p[0], *p1 = p[1], *p2 = p[2], *p3 = p[3]; const int *pq0 = pq[0], *pq1 = pq[1], *pq2 = pq[2], *pq3 = pq[3]; bool doCannyPruning = p0 != 0; @@ -1449,7 +1462,11 @@ struct HaarDetectObjects_ScaleCascade_Invoker int result = cvRunHaarClassifierCascade( cascade, cvPoint(x, y), 0 ); if( result > 0 ) + { + mtx->lock(); vec->push_back(Rect(x, y, winsize.width, winsize.height)); + mtx->unlock(); + } ixstep = result != 0 ? 1 : 2; } } @@ -1462,7 +1479,8 @@ struct HaarDetectObjects_ScaleCascade_Invoker Range xrange; const int** p; const int** pq; - ConcurrentRectVector* vec; + std::vector* vec; + Mutex* mtx; }; @@ -1482,7 +1500,7 @@ cvHaarDetectObjectsForROC( const CvArr* _img, CvSeq* result_seq = 0; cv::Ptr temp_storage; - cv::ConcurrentRectVector allCandidates; + std::vector allCandidates; std::vector rectList; std::vector rweights; double factor; @@ -1490,6 +1508,7 @@ cvHaarDetectObjectsForROC( const CvArr* _img, bool doCannyPruning = (flags & CV_HAAR_DO_CANNY_PRUNING) != 0; bool findBiggestObject = (flags & CV_HAAR_FIND_BIGGEST_OBJECT) != 0; bool roughSearch = (flags & CV_HAAR_DO_ROUGH_SEARCH) != 0; + cv::Mutex mtx; if( !CV_IS_HAAR_CLASSIFIER(cascade) ) CV_Error( !cascade ? CV_StsNullPtr : CV_StsBadArg, "Invalid classifier cascade" ); @@ -1599,11 +1618,11 @@ cvHaarDetectObjectsForROC( const CvArr* _img, cvSetImagesForHaarClassifierCascade( cascade, &sum1, &sqsum1, _tilted, 1. ); cv::Mat _norm1(&norm1), _mask1(&mask1); - cv::parallel_for(cv::BlockedRange(0, stripCount), + cv::parallel_for_(cv::Range(0, stripCount), cv::HaarDetectObjects_ScaleImage_Invoker(cascade, (((sz1.height + stripCount - 1)/stripCount + ystep-1)/ystep)*ystep, factor, cv::Mat(&sum1), cv::Mat(&sqsum1), &_norm1, &_mask1, - cv::Rect(equRect), allCandidates, rejectLevels, levelWeights, outputRejectLevels)); + cv::Rect(equRect), allCandidates, rejectLevels, levelWeights, outputRejectLevels, &mtx)); } } else @@ -1695,10 +1714,10 @@ cvHaarDetectObjectsForROC( const CvArr* _img, endX = cvRound((scanROI.x + scanROI.width - winSize.width) / ystep); } - cv::parallel_for(cv::BlockedRange(startY, endY), + cv::parallel_for_(cv::Range(startY, endY), cv::HaarDetectObjects_ScaleCascade_Invoker(cascade, winSize, cv::Range(startX, endX), ystep, sum->step, (const int**)p, - (const int**)pq, allCandidates )); + (const int**)pq, allCandidates, &mtx )); if( findBiggestObject && !allCandidates.empty() && scanROI.area() == 0 ) { From 0e2958e8884ced786c934eb0c4563fd3eec7a1fc Mon Sep 17 00:00:00 2001 From: Maria Dimashova Date: Sat, 29 Dec 2012 00:30:52 +0400 Subject: [PATCH 23/34] fixed CvBoost::predict (Sometimes sample_data became bad because the buffer with its values was deallocated early). --- modules/ml/src/boost.cpp | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/modules/ml/src/boost.cpp b/modules/ml/src/boost.cpp index eb8bebc79..3525a1173 100644 --- a/modules/ml/src/boost.cpp +++ b/modules/ml/src/boost.cpp @@ -1598,7 +1598,6 @@ CvBoost::predict( const CvMat* _sample, const CvMat* _missing, { float value = -FLT_MAX; - CvMat sample, missing; CvSeqReader reader; double sum = 0; int wstep = 0; @@ -1648,10 +1647,15 @@ CvBoost::predict( const CvMat* _sample, const CvMat* _missing, const int* cmap = data->cat_map->data.i; const int* cofs = data->cat_ofs->data.i; + cv::Mat sample = _sample; + cv::Mat missing; + if(!_missing) + missing = _missing; + // if need, preprocess the input vector if( !raw_mode ) { - int step, mstep = 0; + int sstep, mstep = 0; const float* src_sample; const uchar* src_mask = 0; float* dst_sample; @@ -1660,12 +1664,14 @@ CvBoost::predict( const CvMat* _sample, const CvMat* _missing, const int* vidx_abs = active_vars_abs->data.i; bool have_mask = _missing != 0; - cv::AutoBuffer buf(var_count + (var_count+3)/4); - dst_sample = &buf[0]; - dst_mask = (uchar*)&buf[var_count]; + sample = cv::Mat(1, var_count, CV_32FC1); + missing = cv::Mat(1, var_count, CV_8UC1); + + dst_sample = sample.ptr(); + dst_mask = missing.ptr(); src_sample = _sample->data.fl; - step = CV_IS_MAT_CONT(_sample->type) ? 1 : _sample->step/sizeof(src_sample[0]); + sstep = CV_IS_MAT_CONT(_sample->type) ? 1 : _sample->step/sizeof(src_sample[0]); if( _missing ) { @@ -1676,7 +1682,7 @@ CvBoost::predict( const CvMat* _sample, const CvMat* _missing, for( i = 0; i < var_count; i++ ) { int idx = vidx[i], idx_abs = vidx_abs[i]; - float val = src_sample[idx_abs*step]; + float val = src_sample[idx_abs*sstep]; int ci = vtype[idx]; uchar m = src_mask ? src_mask[idx_abs*mstep] : (uchar)0; @@ -1715,14 +1721,8 @@ CvBoost::predict( const CvMat* _sample, const CvMat* _missing, dst_mask[i] = m; } - sample = cvMat( 1, var_count, CV_32F, dst_sample ); - _sample = &sample; - - if( have_mask ) - { - missing = cvMat( 1, var_count, CV_8UC1, dst_mask ); - _missing = &missing; - } + if( !have_mask ) + missing.release(); } else { @@ -1733,9 +1733,9 @@ CvBoost::predict( const CvMat* _sample, const CvMat* _missing, cvStartReadSeq( weak, &reader ); cvSetSeqReaderPos( &reader, slice.start_index ); - sample_data = _sample->data.fl; + sample_data = sample.ptr(); - if( !have_active_cat_vars && !_missing && !weak_responses ) + if( !have_active_cat_vars && missing.empty() && !weak_responses ) { for( i = 0; i < weak_count; i++ ) { @@ -1760,7 +1760,7 @@ CvBoost::predict( const CvMat* _sample, const CvMat* _missing, else { const int* avars = active_vars->data.i; - const uchar* m = _missing ? _missing->data.ptr : 0; + const uchar* m = !missing.empty() ? missing.ptr() : 0; // full-featured version for( i = 0; i < weak_count; i++ ) @@ -2147,5 +2147,3 @@ CvBoost::predict( const Mat& _sample, const Mat& _missing, } /* End of file. */ - - From da9089612a12639d1851798982f7f79af77ba181 Mon Sep 17 00:00:00 2001 From: Andrey Kamaev Date: Sun, 30 Dec 2012 23:24:39 +0400 Subject: [PATCH 24/34] Fix build of java bindings on mingw --- modules/java/generator/gen_java.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/modules/java/generator/gen_java.py b/modules/java/generator/gen_java.py index c60730fad..429360cd2 100755 --- a/modules/java/generator/gen_java.py +++ b/modules/java/generator/gen_java.py @@ -1243,6 +1243,10 @@ extern "C" { jni_name = "&%(n)s" else: jni_name = "%(n)s" + if not a.out and not "jni_var" in type_dict[a.ctype]: + # explicit cast to C type to avoid ambiguous call error on platforms (mingw) + # where jni types are different from native types (e.g. jint is not the same as int) + jni_name = "(%s)%s" % (a.ctype, jni_name) if not a.ctype: # hidden jni_name = a.defval cvargs.append( type_dict[a.ctype].get("jni_name", jni_name) % {"n" : a.name}) @@ -1267,8 +1271,7 @@ JNIEXPORT $rtype JNICALL Java_org_opencv_${module}_${clazz}_$fname LOGD("$module::$fname()"); $prologue $retval$cvname( $cvargs ); - $epilogue - $ret + $epilogue$ret } catch(cv::Exception e) { LOGD("$module::$fname() catched cv::Exception: %s", e.what()); jclass je = env->FindClass("org/opencv/core/CvException"); @@ -1292,7 +1295,7 @@ JNIEXPORT $rtype JNICALL Java_org_opencv_${module}_${clazz}_$fname args = ", ".join(["%s %s" % (type_dict[a.ctype].get("jni_type"), a.name) for a in jni_args]), \ argst = ", ".join([type_dict[a.ctype].get("jni_type") for a in jni_args]), \ prologue = "\n ".join(c_prologue), \ - epilogue = " ".join(c_epilogue), \ + epilogue = " ".join(c_epilogue) + ("\n " if c_epilogue else ""), \ ret = ret, \ cvname = cvname, \ cvargs = ", ".join(cvargs), \ From a09b973c2eb47a13f316c3987feefaa989c6be8a Mon Sep 17 00:00:00 2001 From: Anatoly Baksheev Date: Fri, 21 Dec 2012 23:27:29 +0400 Subject: [PATCH 25/34] Smart operators for smart Ptr (feature #2637) --- modules/core/include/opencv2/core/core.hpp | 5 +++-- modules/core/include/opencv2/core/operations.hpp | 9 +++++---- modules/core/src/persistence.cpp | 2 +- modules/features2d/src/matchers.cpp | 4 ++-- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/modules/core/include/opencv2/core/core.hpp b/modules/core/include/opencv2/core/core.hpp index 5b8ee6379..94d7526aa 100644 --- a/modules/core/include/opencv2/core/core.hpp +++ b/modules/core/include/opencv2/core/core.hpp @@ -1277,12 +1277,13 @@ public: operator _Tp* (); operator const _Tp*() const; - bool operator==(const Ptr<_Tp>& ptr) const; - _Tp* obj; //< the object pointer. int* refcount; //< the associated reference counter }; +template bool operator==(Ptr const & a, Ptr const & b); +template bool operator!=(Ptr const & a, Ptr const & b); + //////////////////////// Input/Output Array Arguments ///////////////////////////////// diff --git a/modules/core/include/opencv2/core/operations.hpp b/modules/core/include/opencv2/core/operations.hpp index aaabe5f51..eaae0c0b1 100644 --- a/modules/core/include/opencv2/core/operations.hpp +++ b/modules/core/include/opencv2/core/operations.hpp @@ -2691,10 +2691,11 @@ template template inline const Ptr<_Tp2> Ptr<_Tp>:: return p; } -template inline bool Ptr<_Tp>::operator==(const Ptr<_Tp>& _ptr) const -{ - return refcount == _ptr.refcount; -} +template inline bool operator==(const Ptr<_Tp>& a, const Ptr<_Tp2>& b) { return a.refcount == b.refcount; } +template inline bool operator!=(const Ptr<_Tp>& a, const Ptr<_Tp2>& b) { return a.refcount != b.refcount; } + + + //// specializied implementations of Ptr::delete_obj() for classic OpenCV types diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index aee20b3e0..f87364c7c 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -5519,7 +5519,7 @@ void read( const FileNode& node, SparseMat& mat, const SparseMat& default_mat ) return; } Ptr m = (CvSparseMat*)cvRead((CvFileStorage*)node.fs, (CvFileNode*)*node); - CV_Assert(CV_IS_SPARSE_MAT(m)); + CV_Assert(CV_IS_SPARSE_MAT(m.obj)); SparseMat(m).copyTo(mat); } diff --git a/modules/features2d/src/matchers.cpp b/modules/features2d/src/matchers.cpp index aac9e6b93..e82b1738b 100644 --- a/modules/features2d/src/matchers.cpp +++ b/modules/features2d/src/matchers.cpp @@ -616,7 +616,7 @@ void FlannBasedMatcher::write( FileStorage& fs) const { fs << "indexParams" << "["; - if (indexParams != 0) + if (indexParams) { std::vector names; std::vector types; @@ -667,7 +667,7 @@ void FlannBasedMatcher::write( FileStorage& fs) const fs << "]" << "searchParams" << "["; - if (searchParams != 0) + if (searchParams) { std::vector names; std::vector types; From 4e1ba6f02fa5ca2241b61a8a32970ca2b5653e97 Mon Sep 17 00:00:00 2001 From: Andrey Kamaev Date: Mon, 31 Dec 2012 04:17:36 +0400 Subject: [PATCH 26/34] Fix build with libjpeg release 9 --- modules/highgui/src/grfmt_jpeg.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/highgui/src/grfmt_jpeg.cpp b/modules/highgui/src/grfmt_jpeg.cpp index 6ecf2d654..521517639 100644 --- a/modules/highgui/src/grfmt_jpeg.cpp +++ b/modules/highgui/src/grfmt_jpeg.cpp @@ -63,6 +63,9 @@ typedef unsigned char boolean; #endif +#undef FALSE +#undef TRUE + extern "C" { #include "jpeglib.h" } From e383d39598e4f09063067ed2f4953d8dbd756b3a Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Wed, 9 Jan 2013 17:53:19 +0400 Subject: [PATCH 27/34] fixed bug #2679 --- modules/imgproc/src/templmatch.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/imgproc/src/templmatch.cpp b/modules/imgproc/src/templmatch.cpp index 5e1ad2034..0a3b95d7c 100644 --- a/modules/imgproc/src/templmatch.cpp +++ b/modules/imgproc/src/templmatch.cpp @@ -346,7 +346,10 @@ void cv::matchTemplate( InputArray _img, InputArray _templ, OutputArray _result, } if( numType == 2 ) + { num = wndSum2 - 2*num + templSum2; + num = MAX(num, 0.); + } } if( isNormed ) From 0334cf11cc7dab63bf7e95f4e970960350eac0b6 Mon Sep 17 00:00:00 2001 From: Anna Kogan Date: Thu, 10 Jan 2013 13:16:46 +0400 Subject: [PATCH 28/34] Fixed last testsuit disregarding --- modules/ts/misc/perf_tests_timing.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/ts/misc/perf_tests_timing.py b/modules/ts/misc/perf_tests_timing.py index 70d2aa2f0..bf9d06c3c 100644 --- a/modules/ts/misc/perf_tests_timing.py +++ b/modules/ts/misc/perf_tests_timing.py @@ -81,6 +81,9 @@ if __name__ == "__main__": if case.get('status') == 'failed': has_failed = True + testsuits.append({'name': prevGroupName, 'time': suit_time, \ + 'failed': has_failed}) + tbl = table() # header From 0d7ce141aad0d5c908d077f29e69f74dd7fac863 Mon Sep 17 00:00:00 2001 From: Anna Kogan Date: Thu, 10 Jan 2013 13:18:26 +0400 Subject: [PATCH 29/34] Cleaned code --- modules/ts/misc/perf_tests_timing.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/ts/misc/perf_tests_timing.py b/modules/ts/misc/perf_tests_timing.py index bf9d06c3c..4a9f39af7 100644 --- a/modules/ts/misc/perf_tests_timing.py +++ b/modules/ts/misc/perf_tests_timing.py @@ -21,14 +21,12 @@ if __name__ == "__main__": options.generateHtml = detectHtmlOutputType(options.format) - # expand wildcards and filter duplicates file = os.path.abspath(args[0]) if not os.path.isfile(file): sys.stderr.write("IOError reading \"" + file + "\" - " + str(err) + os.linesep) parser.print_help() exit(0) - # read all passed files test_sets = [] try: tests = testlog_parser.parseLogFile(file) @@ -41,7 +39,7 @@ if __name__ == "__main__": if not test_sets: sys.stderr.write("Error: no test data found" + os.linesep) - quit() + exit(0) # find matches setsCount = len(test_sets) @@ -84,6 +82,10 @@ if __name__ == "__main__": testsuits.append({'name': prevGroupName, 'time': suit_time, \ 'failed': has_failed}) + if len(testsuits)==0: + print 'No testsuits found' + exit(0) + tbl = table() # header From 3271e395c84a0f8298cbee3c8efdd00ea6decbf3 Mon Sep 17 00:00:00 2001 From: Anna Kogan Date: Thu, 10 Jan 2013 13:19:59 +0400 Subject: [PATCH 30/34] Improved console output --- modules/ts/misc/perf_tests_timing.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/modules/ts/misc/perf_tests_timing.py b/modules/ts/misc/perf_tests_timing.py index 4a9f39af7..781bfdfd2 100644 --- a/modules/ts/misc/perf_tests_timing.py +++ b/modules/ts/misc/perf_tests_timing.py @@ -5,6 +5,7 @@ from table_formatter import * from optparse import OptionParser from operator import itemgetter, attrgetter from summary import getSetName, alphanum_keyselector +import re if __name__ == "__main__": usage = "%prog .xml [...]" @@ -21,7 +22,8 @@ if __name__ == "__main__": options.generateHtml = detectHtmlOutputType(options.format) - file = os.path.abspath(args[0]) + input_file = args[0] + file = os.path.abspath(input_file) if not os.path.isfile(file): sys.stderr.write("IOError reading \"" + file + "\" - " + str(err) + os.linesep) parser.print_help() @@ -108,4 +110,11 @@ if __name__ == "__main__": tbl.htmlPrintTable(sys.stdout) htmlPrintFooter(sys.stdout) else: - tbl.consolePrintTable(sys.stdout) \ No newline at end of file + input_file = re.sub(r'^[\.\/]*', '', input_file) + find_module_name = re.search(r'([^_]*)', input_file) + module_name = find_module_name.group(0) + + splitter = 15 * '*' + print '\n%s\n %s\n%s\n' % (splitter, module_name, splitter) + tbl.consolePrintTable(sys.stdout) + print 4 * '\n' \ No newline at end of file From 6131a847a29314e39686810f3632a924ab071850 Mon Sep 17 00:00:00 2001 From: Andrey Kamaev Date: Thu, 10 Jan 2013 14:45:00 +0400 Subject: [PATCH 31/34] Fix histogram calculation in equalizeHist issue #2678 --- modules/imgproc/src/histogram.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgproc/src/histogram.cpp b/modules/imgproc/src/histogram.cpp index 3f0c3daa2..864b49b31 100644 --- a/modules/imgproc/src/histogram.cpp +++ b/modules/imgproc/src/histogram.cpp @@ -3023,7 +3023,7 @@ public: localHistogram[t0]++; localHistogram[t1]++; } - for (; x < width; ++x, ++ptr) + for (; x < width; ++x) localHistogram[ptr[x]]++; } From 20c5a8788d922f86bc636363addeeacff1312c61 Mon Sep 17 00:00:00 2001 From: Andrey Kamaev Date: Thu, 10 Jan 2013 17:12:14 +0400 Subject: [PATCH 32/34] Weaken acceptance criteria in phase test --- modules/core/test/test_math.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/core/test/test_math.cpp b/modules/core/test/test_math.cpp index 0558ab0c2..21c8cb4d5 100644 --- a/modules/core/test/test_math.cpp +++ b/modules/core/test/test_math.cpp @@ -2430,8 +2430,8 @@ protected: } Mat convertedRes = resInRad * 180. / CV_PI; - double normDiff = norm(convertedRes - resInDeg); - if(normDiff > FLT_EPSILON) + double normDiff = norm(convertedRes - resInDeg, NORM_INF); + if(normDiff > FLT_EPSILON * 180.) { ts->printf(cvtest::TS::LOG, "There are incorrect result angles (in radians)\n"); ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); From b1384a6da882d8626573f3e67d62b823f7912cd6 Mon Sep 17 00:00:00 2001 From: Andrey Kamaev Date: Thu, 10 Jan 2013 18:14:08 +0400 Subject: [PATCH 33/34] Fix cvCalcOpticalFlow when the status parameter is NULL issue 2526 --- modules/video/src/lkpyramid.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/video/src/lkpyramid.cpp b/modules/video/src/lkpyramid.cpp index 552bfbda2..bad555862 100644 --- a/modules/video/src/lkpyramid.cpp +++ b/modules/video/src/lkpyramid.cpp @@ -1194,8 +1194,8 @@ cvCalcOpticalFlowPyrLK( const void* arrA, const void* arrB, st = cv::Mat(count, 1, CV_8U, (void*)status); if( error ) err = cv::Mat(count, 1, CV_32F, (void*)error); - cv::calcOpticalFlowPyrLK( A, B, ptA, ptB, status ? cv::_OutputArray(st) : cv::_OutputArray(), - error ? cv::_OutputArray(err) : cv::_OutputArray(), + cv::calcOpticalFlowPyrLK( A, B, ptA, ptB, st, + error ? cv::_OutputArray(err) : cv::noArray(), winSize, level, criteria, flags); } From cf8deac2b2882954f94aaeaca7638cead4500769 Mon Sep 17 00:00:00 2001 From: Andrey Kamaev Date: Thu, 10 Jan 2013 19:05:39 +0400 Subject: [PATCH 34/34] Always touch variable controlling build of the module This suppresses "unused variable" CMake warning when user explicilty disables module unavailable in selected configuration --- cmake/OpenCVModule.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/OpenCVModule.cmake b/cmake/OpenCVModule.cmake index 91b65f59a..9d5ce074b 100644 --- a/cmake/OpenCVModule.cmake +++ b/cmake/OpenCVModule.cmake @@ -164,6 +164,9 @@ macro(ocv_module_disable module) set(HAVE_${__modname} OFF CACHE INTERNAL "Module ${__modname} can not be built in current configuration") set(OPENCV_MODULE_${__modname}_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "Location of ${__modname} module sources") set(OPENCV_MODULES_DISABLED_FORCE "${OPENCV_MODULES_DISABLED_FORCE}" CACHE INTERNAL "List of OpenCV modules which can not be build in current configuration") + if(BUILD_${__modname}) + # touch variable controlling build of the module to suppress "unused variable" CMake warning + endif() unset(__modname) return() # leave the current folder endmacro()