0

I have an image that has been processed throw:

//UIImage to Mat
cv::Mat originalMat = [self cvMatFromUIImage:inputImage];

//Grayscale
cv::Mat grayMat;
cv::cvtColor(originalMat, grayMat, CV_RGB2GRAY);

//Blur
cv::Mat gaussMat;
cv::GaussianBlur( grayMat , gaussMat, cv::Size(9, 9), 2, 2 );

//Threshold
cv::threshold(grayMat,tMat,100,255,cv::THRESH_BINARY);

than I want to analyze (calculate qty of white and black points) that belows to line. For instance: I have an image 100x120px and I want to check lines where x = 5 and y = from 0 to 119; and vice versa x = 0..99; y = 5;

so I expect that Mat will contains x - Mat.cols and y - Mat.rows but looks it saves data in another way. for example I've tried to change pixels color that belows to lines but didn't get 2 lines:

for( int x = 0; x < tMat.cols; x++ ){
    tMat.at<cv::Vec4b>(5,x)[0] = 100;
}

for( int y = 0; y < tMat.rows; y++ ){
    tMat.at<cv::Vec4b>(y,5)[0] = 100;
}
return  [self UIImageFromCVMat:tMat];

result for white image:

enter image description here

why I did't get 2 lines? Is it possible to draw\check lines in Mat directly? what if I going to check line that calculates via y = kx + b?

Siarhei
  • 2,358
  • 3
  • 27
  • 63

2 Answers2

3

You are accessing the pixel values in the wrong way. You are working with image that only has one channel, that's why you should access pixel values like this:

for (int x = 0; x < tMat.cols; x++){
    tMat.at<unsigned char>(5, x) = 100;
}

for (int y = 0; y < tMat.rows; y++){
    tMat.at<unsigned char>(y, 5) = 100;
}

The Mat element's type is defined by two properties - the number of channels and the underlying type of data. If you do not know the meaning of those terms, I strongly suggest that you read the documentation for methods cv::Mat::type(), cv::Mat::channels() and cv::Mat::depth().

Two more examples:

mat.at<float>(x, y) = 1.0f; // if mat type is CV_32FC1
mat.at<cv::Vec3b>(x, y) = Vec3b(1, 2, 3); // if mat type is CV_8UC3
Nejc
  • 927
  • 6
  • 15
2

Probably an issue with your Mat data types. The output of threshold is a single channel image that is 8-bit or 32-bit (http://docs.opencv.org/2.4/modules/imgproc/doc/miscellaneous_transformations.html?highlight=threshold#threshold), so you probably should not be setting values with Mat.at<Vec4b>[0].

Here's a function to return the type of your matrix. Usage is in the commented out part. Copied from How to find out what type of a Mat object is with Mat::type() in OpenCV.

std::string type2str(int type){
//string ty =  type2str( comparisonResult.type() );
//printf("Matrix: %s %dx%d \n", ty.c_str(), comparisonResult.cols, comparisonResult.rows );

string r;

uchar depth = type & CV_MAT_DEPTH_MASK;
uchar chans = 1 + (type >> CV_CN_SHIFT);

switch ( depth ) {
case CV_8U:  r = "8U"; break;
case CV_8S:  r = "8S"; break;
case CV_16U: r = "16U"; break;
case CV_16S: r = "16S"; break;
case CV_32S: r = "32S"; break;
case CV_32F: r = "32F"; break;
case CV_64F: r = "64F"; break;
default:     r = "User"; break;
}

r += "C";
r += (chans+'0');

return r;}
Community
  • 1
  • 1
chloelle
  • 332
  • 3
  • 12