Ask Your Question

Nina's profile - activity

2019-11-03 15:52:13 -0600 received badge  Notable Question (source)
2018-06-21 09:01:22 -0600 received badge  Popular Question (source)
2016-04-25 01:35:31 -0600 received badge  Nice Question (source)
2015-06-25 01:42:46 -0600 asked a question OpenCV Error: Assertion failed in watershed
cv::Mat image;
UIImageToMat(input, image, false);
cv::Mat binary;
cv::cvtColor(image, binary, COLOR_BGR2GRAY);
cv::threshold(binary, binary, 100, 255, THRESH_BINARY);

    // Eliminate noise and smaller objects
cv::Mat fg;
cv::erode(binary,fg,cv::Mat(),cv::Point(-1,-1),2);

    // Identify image pixels without objects
cv::Mat bg;
cv::dilate(binary,bg,cv::Mat(),cv::Point(-1,-1),3);
cv::threshold(bg,bg,1, 128,cv::THRESH_BINARY_INV);

    // Create markers image
markers= fg+bg;
    // Create watershed segmentation object
WatershedSegmenter segmenter;
segmenter.setMarkers(markers);

cv::Mat result = segmenter.process(image);
result.convertTo(result,CV_8U);
return MatToUIImage(result);

class WatershedSegmenter{
private:
cv::Mat markers;
public:
void setMarkers(cv::Mat& markerImage)
{
markerImage.convertTo(markers, CV_32S);
}

cv::Mat process(cv::Mat &image)
{
cv::watershed(image, markers);
markers.convertTo(markers,CV_8U);
return markers;
}
};

While learning about OpenCV I came across the topic of segmentation, and found a thread here. I tried my hand at the provided answer and got the following error,

OpenCV Error: Assertion failed (src.type() == CV_8UC3 && dst.type() == CV_32SC1) in watershed, file /Users/siva/working/opencv/modules/imgproc/src/segmentation.cpp, line 147

And couldn't figure out a solution as I'm new to this topic. Any suggestions/solutions please?

2015-06-16 00:31:10 -0600 received badge  Enthusiast
2015-06-09 06:36:49 -0600 commented question Could not perform 'fill' using draw contours

It looked so. I wasn't sure about it. So I again performed canny, findContours, fillContours on the result from above code. The result was same as earlier.

2015-06-09 05:20:36 -0600 commented question Could not perform 'fill' using draw contours

@StevenPuttemans Nope. That gives the same result.

2015-06-05 09:28:06 -0600 asked a question Could not perform 'fill' using draw contours

Complete Code

cv::Mat img, output;
UIImageToMat(input, img, false);

cv::Mat grayed;
cv::cvtColor(img, grayed, COLOR_BGR2GRAY);
cv::GaussianBlur(grayed, grayed, cv::Size(7, 7), 2);

int erosion_size = 1;
cv::Mat element = cv::getStructuringElement(0, cv::Size(erosion_size + 1, erosion_size + 1), cv::Point(1, 1));
cv::Mat temp;

cv::morphologyEx(grayed, temp, MORPH_GRADIENT, element);
cv::Mat dilateKernel(cv::Size(7, 7), CV_8UC1, cv::Scalar(1));
cv::dilate(temp, temp, dilateKernel);
cv::bitwise_not(temp, temp);
adaptiveThreshold(~temp, temp, 255, ADAPTIVE_THRESH_MEAN_C, 0, 207, -2);

    //skel
cv::Mat skel(grayed.size(), CV_8UC1, cv::Scalar(0));
cv::Mat temp1(grayed.size(), CV_8UC1);
cv::Mat element1 = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(3, 3));
bool done;
do {
    cv::morphologyEx(temp, temp1, cv::MORPH_OPEN, element1);
    cv::bitwise_not(temp1, temp1);
    cv::bitwise_and(temp, temp1, temp1);
    cv::bitwise_or(skel, temp1, skel);
    cv::erode(temp, temp, element1);

    double max;
    cv::minMaxLoc(temp, 0, &max);
    done = (max == 0);

} while (!done);

    //contour
vector<vector<cv::Point> > contours;
vector<Vec4i> hierarchy;
findContours( skel, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

Mat drawing = Mat::zeros( skel.size(), CV_8UC3 );

for( int i = 0; i< contours.size(); i++ ) {

    std::vector<cv::Point> contour_line;
    cv::approxPolyDP(cv::Mat(contours[i]), contour_line, 5, true);
    int nc = (int)contour_line.size();
    const cv::Point * pc = &(contour_line[0]);
    cv::polylines( drawing, &pc, &nc, 1, 0, cv::Scalar(255, 255, 255), nc, FILLED);
    drawContours(drawing, contours, i, Scalar(200, 200, 0), FILLED);
}
return MatToUIImage(drawing);

Question

I have followed this tutorial for Morphological Skeleton. The input and the skeleton result are here.

After performing morphological Skeleton operation, I'm processing findContours and filling it with drawContours. However the end result is not as expected. It thickens the border of each letter instead of filling. Could anyone advice what am I missing? Or do I need to perform any other operation instead of drawContours?

Note: This is most likely a follow-up question of my previous one.

2015-06-05 04:51:49 -0600 received badge  Scholar (source)
2015-06-04 09:11:56 -0600 received badge  Supporter (source)
2015-06-04 08:22:09 -0600 commented answer Gap filling in letters

Thank you! I will try the suggested solution..

2015-06-04 08:09:30 -0600 commented answer Gap filling in letters

For cvtColor code 0 is COLOR_BGR2BGRA? It works only if I change it to Grayscale. And the text "2" on top left and its background is just reversed. Is there any solution for it?

2015-06-04 07:40:08 -0600 commented question Gap filling in letters

@LBerger Thank you! The result image is too perfect. But I couldn't understand the xml, as I'm fairly new to opencv. Is it possible for a pseudo-code or something?

2015-06-04 06:47:59 -0600 received badge  Student (source)
2015-06-04 05:34:58 -0600 received badge  Editor (source)
2015-06-04 01:07:34 -0600 received badge  Organizer (source)
2015-06-04 00:41:36 -0600 asked a question Gap filling in letters

Reading text from image is a part of iOS application, I'm currently in. We are using OpenCV to process image before sending it to tesseract. I have read in an article, it is advisable to have black text on white background to achieve higher success rate in reading.This is the original image without cropping

By performing the following on the image (cropped & orientation fixed), we get the following result.

cv::Mat img;
UIImageToMat(input, img, false);
cv::Mat grayed;
cv::cvtColor(img, grayed, COLOR_BGR2GRAY);

int erosion_size = 12.0;
cv::Mat element = cv::getStructuringElement(0, cv::Size(erosion_size + 1, erosion_size + 1), cv::Point(1, 1));

cv::Mat temp;
cv::morphologyEx(grayed, temp, BORDER_WRAP, element);

cv::bitwise_not(temp, temp);
adaptiveThreshold(~temp, temp, 255, ADAPTIVE_THRESH_MEAN_C, 0, 15, -2);
double otsu_thresh_val = threshold(temp, temp, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);
if (otsu_thresh_val == 0)
    otsu_thresh_val = 100;
double high_thresh_val  = otsu_thresh_val, lower_thresh_val = otsu_thresh_val * 0.5;

[Step 1] http://s6.postimg.org/sflk5g9sx/step1...

Now, the remaining part is filling the letters with black color. Read dilation after canny makes the border line thicker , which I thought would fill the letters inwards. But I'm proved wrong. Code:

cv::Mat canny_output;
Canny( temp, canny_output, lower_thresh_val, high_thresh_val, 3 );
cv::dilate( canny_output, canny_output, element, cv::Point(-1, -1), 1);//1 iteration

[Step 2]http://s6.postimg.org/tj5oheug1/Step2.png

As another approach, I have tried to find contours and fill. Applied canny w/o dilation. Code:

    Canny( temp, canny_output, lower_thresh_val, high_thresh_val, 3 );
vector<vector<cv::Point> > contours;
vector<Vec4i> hierarchy;
RNG rng(12345);
findContours( canny_output, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, cv::Point(1, 1));
cv::Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 );

vector<cv::Point> approxShape;
for(int i = 0; i < contours.size(); i++){
    approxPolyDP(contours[i], approxShape, arcLength(Mat(contours[i]), true)*0.04, true);
    drawContours(drawing, contours, i, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), FILLED);   // fill random color
}

[Step 3]http://s6.postimg.org/yvuivjich/step3.png

Which fills the inner holes. This is my first try at OpenCV, probably i'm misunderstanding the codes and its intended concept. It would be of great help, if someone could point me out the mistakes and/or in which direction i should proceed further.

Regards.

EDIT: UPDATED CODE

    cv::Mat img, output;
UIImageToMat(input, img, false);
cv::Mat grayed;
cv::cvtColor(img, grayed, COLOR_BGR2GRAY);

int erosion_size = 12.0;
cv::Mat element = cv::getStructuringElement(0, cv::Size(erosion_size + 1, erosion_size + 1), cv::Point(1, 1));
cv::Mat temp;
cv::morphologyEx(grayed, temp, MORPH_RECT, element);

cv::GaussianBlur(temp, temp, cv::Size(7, 7), 2);
cv::bitwise_not(temp, temp);
adaptiveThreshold(~temp, temp, 255, ADAPTIVE_THRESH_MEAN_C, 0, 207, -2);

cv::medianBlur(temp, temp, 3);
cv::Mat binary;
double otsu_thresh_val = cv::threshold(temp, binary, 225, 255, cv::THRESH_BINARY_INV);
cv::erode(binary, binary, element);
cv::dilate(binary, binary, element);

if (otsu_thresh_val == 0)
    otsu_thresh_val = 100;
double high_thresh_val  = otsu_thresh_val, lower_thresh_val = otsu_thresh_val * 0.5;

cv::Mat canny_output;
Canny( binary, canny_output, lower_thresh_val, high_thresh_val, 3 );

bitwise_not(canny_output, canny_output);
const int connectivity_8 = 4;
Mat labels, stats, centroids;
int nLabels = connectedComponentsWithStats(canny_output, labels, stats ...
(more)