Repository: opencv
Issue: cv::connectedComponentsWithStats crashes
Labels: bug,category: imgproc

##### System information (version)

- OpenCV => 3.3.1 and latest master (3.4rc)
- Operating System / Platform => Debian Linux (Sid)
- Compiler => gcc 7.2.0

##### Detailed description

Using `cv::connectedComponentsWithStats` crashes in gdb as well as valgrind, and triggers an assertion if OpenCV is compiled with debugging information. 

valgrind says:
```
==12872== Invalid read of size 4
==12872==    at 0x7650D7D: cv::connectedcomponents::CCStatsOp::operator()(int, int, int) (connectedcomponents.cpp:137)
==12872==    by 0x7669E1F: cv::connectedcomponents::LabelingGrana<unsigned short, unsigned char, cv::connectedcomponents::CCStatsOp>::operator()(cv::Mat const&, cv::Mat&, int, cv::connectedcomponents::CCStatsOp&) (connectedcomponents.cpp:3764)
==12872==    by 0x76520D3: int cv::connectedComponents_sub1<cv::connectedcomponents::CCStatsOp>(cv::Mat const&, cv::Mat&, int, int, cv::connectedcomponents::CCStatsOp&) (connectedcomponents.cpp:3977)
==12872==    by 0x76516AF: cv::connectedComponentsWithStats(cv::_InputArray const&, cv::_OutputArray const&, cv::_OutputArray const&, cv::_OutputArray const&, int, int, int) (connectedcomponents.cpp:4032)
==12872==    by 0x7651563: cv::connectedComponentsWithStats(cv::_InputArray const&, cv::_OutputArray const&, cv::_OutputArray const&, cv::_OutputArray const&, int, int) (connectedcomponents.cpp:4021)
```

The assertion is:
```
OpenCV Error: Assertion failed ((unsigned)i0 < (unsigned)size.p[0]) in at, file modules/core/include/opencv2/core/mat.inl.hpp, line 1096
```

I then added some more debugging output:
```diff
--- a/modules/core/include/opencv2/core/mat.inl.hpp
+++ b/modules/core/include/opencv2/core/mat.inl.hpp
@@ -54,6 +54,8 @@
 #pragma warning( disable: 4127 )
 #endif
 
+#include <iostream>
+
 namespace cv
 {
 CV__DEBUG_NS_BEGIN
@@ -1091,6 +1093,7 @@ _Tp& Mat::at(int i0, int i1)
 {
     CV_DbgAssert(dims <= 2);
     CV_DbgAssert(data);
+    std::cout << "i0, size: " << (unsigned)i0 << " - " << (unsigned)size.p[0] << std::endl;
     CV_DbgAssert((unsigned)i0 < (unsigned)size.p[0]);
     CV_DbgAssert((unsigned)(i1 * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels()));
     CV_DbgAssert(CV_ELEM_SIZE1(traits::Depth<_Tp>::value) == elemSize1());
@@ -1102,6 +1105,7 @@ const _Tp& Mat::at(int i0, int i1) const
 {
     CV_DbgAssert(dims <= 2);
     CV_DbgAssert(data);
+    std::cout << "i0, size: " << (unsigned)i0 << " - " << (unsigned)size.p[0] << std::endl;
     CV_DbgAssert((unsigned)i0 < (unsigned)size.p[0]);
     CV_DbgAssert((unsigned)(i1 * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels()));
     CV_DbgAssert(CV_ELEM_SIZE1(traits::Depth<_Tp>::value) == elemSize1());
diff --git a/modules/imgproc/src/connectedcomponents.cpp b/modules/imgproc/src/connectedcomponents.cpp
index 0ad7f6780..6220d276a 100644
--- a/modules/imgproc/src/connectedcomponents.cpp
+++ b/modules/imgproc/src/connectedcomponents.cpp
@@ -48,6 +48,8 @@
 #include "precomp.hpp"
 #include <vector>
 
+#include <iostream>
+
 namespace cv{
     namespace connectedcomponents{
 
@@ -131,6 +133,7 @@ namespace cv{
         }
 
         void operator()(int r, int c, int l){
+            std::cout << "CV: r=" << r << " c=" << c << " l=" << l << std::endl;
             int *row =& statsv.at<int>(l, 0);
             row[CC_STAT_LEFT] = MIN(row[CC_STAT_LEFT], c);
             row[CC_STAT_WIDTH] = MAX(row[CC_STAT_WIDTH], c);
```

and got:
```
CV: r=226 c=1247 l=2327
i0, size: 2327 - 1692
OpenCV Error: Assertion failed ....
```
Clearly, some access is going quite wrong here.


##### Steps to reproduce

The image I am using to trigger this bug is attached (it is shown all black, but that is not true - it contains 0 and 1 as colors), the code to execute is this:
```.cpp
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <iostream>

int main(int argc, char** argv)
{
    cv::Mat image = cv::imread("bin-8U.png", cv::IMREAD_GRAYSCALE);

    // after filling with 0 and 1, convert to 8bit for connectedComponentsWithStats
    image.convertTo(image, CV_8UC1);

    cv::Mat1w labels;
    cv::Mat1i stats;
    cv::Mat centroids;
    int numLabels = cv::connectedComponentsWithStats(image, labels, stats, centroids, 8, CV_16U);

    return 0;
}
```
![bin-8u](https://user-images.githubusercontent.com/8768950/34251124-4e2ccd94-e63f-11e7-9660-25e9fe674eca.png)