findChessboardCorners throws Assertion failed (channels() == CV_MAT_CN(dtype)) in copyTo

asked 2017-03-10 15:16:28 -0500

I've been having some strange problems with the findChessboardCorners function, it's been working fine in some parts of my code, but for some reason in other places it's crashing with the error:

OpenCV Error: Assertion failed (channels() == CV_MAT_CN(dtype)) in copyTo, file /tmp/binarydeb/ros-kinetic-opencv3-3.1.0/modules/core/src/copy.cpp, line 257
terminate called after throwing an instance of 'cv::Exception'
  what():  /tmp/binarydeb/ros-kinetic-opencv3-3.1.0/modules/core/src/copy.cpp:257: error: (-215) channels() == CV_MAT_CN(dtype) in function copyTo

I'm testing the type of image immediately before this call and it's a 1000x1000 single channel 8bit unsigned image. The strange thing is I can't understand why findChessboardCorners would be copying the image at all! Here is the source code for the method where the error occurs. If I comment out the call to findChessboardCorners then the code executes without any errors, but obviously doesn't find the calibration target.

Does anyone have any ideas why this function could be throwing this error? I can't seem to find anything about this online at the moment. Many thanks!

void CalibrationCapture::detectTargetInLidarImage()
{
  cv::Mat outputImage(LIDAR_Resolution, LIDAR_Resolution, CV_8UC1, cv::Scalar(0));

  pixelsFilled = 0;
  for (int x=0; x<LIDAR_Resolution; ++x)
    for (int y=0; y<LIDAR_Resolution; ++y)
    {
      int count = intensityCounts.at<int>(y,x);
      if (count > 0)
      {
        ++pixelsFilled;
        unsigned char i = intensityTotals.at<float>(y,x) / count;
        outputImage.at<uchar>(y,x) = i;
      }
    }

  printf("LIDAR intensity image for detection has %d channels.\n", outputImage.channels());

  switch(outputImage.depth())
  {
  case CV_8U: printf("8 bit unsigned\n"); break;
  case CV_8S: printf("8 bit signed\n"); break;
  case CV_16U: printf("16 bit unsigned\n"); break;
  case CV_16S: printf("16 bit signed\n"); break;
  case CV_32S: printf("32 bit signed\n"); break;
  case CV_32F: printf("32 bit float\n"); break;
  }

  // normalize the image and add a small blur to assist in corner detection
  equalizeHist(outputImage, outputImage);
  GaussianBlur(outputImage, outputImage, cv::Size( 3, 3 ), 0, 0 );

  printf("LIDAR intensity image for detection now has %d channels and %d bit depth.\n", outputImage.channels(), outputImage.depth());
  switch(outputImage.depth())
  {
  case CV_8U: printf("8 bit unsigned\n"); break;
  case CV_8S: printf("8 bit signed\n"); break;
  case CV_16U: printf("16 bit unsigned\n"); break;
  case CV_16S: printf("16 bit signed\n"); break;
  case CV_32S: printf("32 bit signed\n"); break;
  case CV_32F: printf("32 bit float\n"); break;
  }

  // try and find calibration target in image
  bool patternFound = cv::findChessboardCorners(outputImage,
                                                patternsize,
                                                lidarCorners,
                                                cv::CALIB_CB_ADAPTIVE_THRESH);

  printf("finished searching for target pattern!\n");

  // if the pattern was found then add a marker to the image
  if (patternFound)
  {
    printf("pattern found!\n");
    cvtColor(outputImage, outputImage, CV_GRAY2RGB);
    cv::drawChessboardCorners(outputImage, patternsize, lidarCorners, true );

    // publish dense intensity image
    if (intensityImagePublisher.getNumSubscribers() > 0)
    {
      cv_bridge::CvImage cvBridgeIntensityImg;
      cvBridgeIntensityImg.encoding = sensor_msgs::image_encodings::TYPE_8UC3;
      cvBridgeIntensityImg.image = outputImage;
      intensityImagePublisher.publish(cvBridgeIntensityImg.toImageMsg());
    }
  }

  // stop lidar scan listener
  scanSub.shutdown();
}
edit retag flag offensive close merge delete