0

I'm new to openCV, I've been getting into the samples provided for Android.

My goals is to detect color-blobs so I started with color-blob-detection sample.

I'm converting color image to grayscale and then thresholding using a binary threshold.

The background is white, blobs are black. I want to detect those black blobs. Also, I would like to draw their contour in color but I'm not able to do it because image is black and white.

I've managed to accomplish this in grayscale but I don't prefer how the contours are drawn, it's like color tolerance is too high and the contour is bigger than the actual blob (maybe blobs are too small?). I guess this 'tolerance' I talk about has something to do with setHsvColor but I don't quite understand that method.

Thanks in advance! Best Regards

UPDATE MORE INFO

The image I want to track is of ink splits. Imagine a white piece of paper with black ink splits. Right now I'm doing it in real-time (camera view). The actual app would take a picture and analyse that picture.

As I said above, I took color-blob-detection sample (android) from openCV GitHub repo. And I add this code in the onCameraFrame method (in order to convert it to black and white in real-time) The convertion is made so I don't mind if ink is black, blue, red:

mRgba = inputFrame.rgba();
/**************************************************************************/
/** BLACK AND WHITE **/
// Convert to Grey
Imgproc.cvtColor(inputFrame.gray(), mRgba, Imgproc.COLOR_GRAY2RGBA, 4);

Mat blackAndWhiteMat = new Mat ( H, W, CvType.CV_8U, new Scalar(1));
double umbral = 100.0;
Imgproc.threshold(mRgba, blackAndWhiteMat , umbral, 255, Imgproc.THRESH_BINARY);

// convert back to bitmap for displaying
Bitmap resultBitmap = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(), Bitmap.Config.ARGB_8888);
blackAndWhiteMat.convertTo(blackAndWhiteMat, CvType.CV_8UC1);
Utils.matToBitmap(blackAndWhiteMat, resultBitmap);
/**************************************************************************/

This may not be the best way but it works.

Now I want to detect black blobs (ink splits). I guess they are detected because the Logcat (log entry of sample app) throws the number of contours detected, but I'm not able to see them because the image is black and white and I want the contour to be red, for example.

Here's an example image:- enter image description here

And here is what I get using RGB (color-blob-detection as is, not black and white image). Notice how small blobs are not detected. (Is it possible to detect them? or are they too small?) enter image description here

Thanks for your help! If you need more info I would gladly update this question

UPDATE: GitHub repo of color-blob-detection sample (second image)

GitHub Repo of openCV sample for Android

saurabheights
  • 3,967
  • 2
  • 31
  • 50
sebasira
  • 1,739
  • 1
  • 22
  • 41
  • Hi, your question is quite uninformative. Please upload the input images and what your processing led to. This will help in understanding the question. As an example, see this question: http://stackoverflow.com/q/10168686/1874627 – saurabheights Nov 24 '16 at 11:39
  • @saurabheights thanks for your comment. I'll update the question with more info and also code snippets – sebasira Nov 24 '16 at 13:22
  • Ok, there are few things I can suggest. Whether small or large blobs should not be an issue, as long as there is a good contrast. If you can find the area where most pixels are white(check connected component), you will have your paper region. In that if you find a sub region to be black(way below average intensity of the paper region), you will find all your blobs. To draw contour, you need convex hull of the black region found. Also, can you upload the code(or link to it) for how you achieved the second image output. It's late here, so will check this tomorrow. Thanks for the good update. – saurabheights Nov 24 '16 at 15:55
  • One small point: Connected Component could be the way blob detection is working(so it may not be a new way to solve the problem). Apply some prior contrast enhancement and gaussian blur(to reduce any noise) before thresholding. And save your intermediate outputs. Generate threshold dynamically(a 100 value will not always work, use some x% of average intensity) – saurabheights Nov 24 '16 at 16:07
  • Thank you again @saurabheights! I'll put the link to the color-blob-detection sample. Sadly, I'm new in this computer vision world and I don't understand how to achieve what you suggest. I understand it (I think) but don't know how to do it with openCV – sebasira Nov 24 '16 at 20:58
  • Hi, it would take some time for me to get free enough to take a good look. I did notice that https://github.com/opencv/opencv/blob/master/samples/android/color-blob-detection/src/org/opencv/samples/colorblobdetect/ColorBlobDetector.java#L71 uses image pyramid. Scaling down on this level is good for speed, but you would lose the small blobs. Second, check image histogram for multimodal distribution(https://en.wikipedia.org/wiki/Multimodal_distribution). If so, otsu method will allow for better thresholding(http://docs.opencv.org/trunk/d7/d4d/tutorial_py_thresholding.html). – saurabheights Nov 26 '16 at 15:36
  • Wow it seems I need to read a lot. I didn't knew about pyramid image, I'll dive into it too. Thanks! – sebasira Nov 27 '16 at 01:05

1 Answers1

0

The solution is based on a combination of adaptive Image thresholding and use of the connected-component algorithm.

Assumption - The paper is the most lit area of the image whereas the ink spots on the paper are darkest regions.

from random import Random
import numpy as np
import cv2

def random_color(random):
    """
    Return a random color
    """
    icolor = random.randint(0, 0xFFFFFF)
    return [icolor & 0xff, (icolor >> 8) & 0xff, (icolor >> 16) & 0xff]

#Read as Grayscale
img = cv2.imread('1-input.jpg', 0)
cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)

# Gaussian to remove noisy region, comment to see its affect.
img = cv2.medianBlur(img,5)

#Find average intensity to distinguish paper region
avgPixelIntensity = cv2.mean( img )
print "Average intensity of image: ", avgPixelIntensity[0]

# Generate mask to distinguish paper region
#0.8 - used to ignore ill-illuminated region of paper
mask = cv2.inRange(img, avgPixelIntensity[0]*0.8, 255) 
mask = 255 - mask
cv2.imwrite('2-maskedImg.jpg', mask)

#Approach 1
# You need to choose 4 or 8 for connectivity type(border pixels)
connectivity = 8
# Perform the operation
output = cv2.connectedComponentsWithStats(mask, connectivity, cv2.CV_8U)
# The first cell is the number of labels
num_labels = output[0]
# The second cell is the label matrix
labels = output[1]
# The third cell is the stat matrix
stats = output[2]
# The fourth cell is the centroid matrix
centroids = output[3]

cv2.imwrite("3-connectedcomponent.jpg", labels)
print "Number of labels", num_labels, labels

# create the random number
random = Random()

for i in range(1, num_labels):
    print stats[i, cv2.CC_STAT_LEFT], stats[i, cv2.CC_STAT_TOP], stats[i, cv2.CC_STAT_WIDTH], stats[i, cv2.CC_STAT_HEIGHT]
    cv2.rectangle(cimg, (stats[i, cv2.CC_STAT_LEFT], stats[i, cv2.CC_STAT_TOP]), 
        (stats[i, cv2.CC_STAT_LEFT] + stats[i, cv2.CC_STAT_WIDTH], stats[i, cv2.CC_STAT_TOP] + stats[i, cv2.CC_STAT_HEIGHT]), random_color(random), 2)

cv2.imwrite("4-OutputImage.jpg", cimg)

The Input Image

The Input Image

Masked Image from thresholding and invert operation.

Masked Image

Use of connected component.

CC Image

Overlaying output of connected component on input image.

Output Image

saurabheights
  • 3,967
  • 2
  • 31
  • 50
  • After posting, I noticed the large orange rectangle. In case you want to ignore it, it should be a simple area estimation compared to the image. Or like checking aspect ratio, a blob will have near same height/width. One question, what is this for? – saurabheights Nov 26 '16 at 17:44
  • @sebasira That's a part of aesthetic, hehe. Why use a black box when you can use rainbow! Also, a black box around a black ink blob won't be very discernible. – saurabheights Nov 27 '16 at 05:37
  • @sebasira: Could you update me on how did it go? It's accuracy as well as pitfalls? Take your time in answering, no hurry. – saurabheights Dec 02 '16 at 19:54
  • 1
    itś very very very close to what I'm looking for. I've managed to build and test your example. Took me some time to set everything up. I'm still working on it and also thinking on some improvements. Now I'm going to try to draw contours on the blobs instead of showing a rectangle. Thank you very much I'll keep you posted or if needed, open a new question – sebasira Dec 02 '16 at 22:30