Alex Crooks
Alex Crooks

Reputation: 97

Finding the area and colours of an object in an image

I have an image that looks like this:

tattoo of woman

And I want to figure out a couple of things:

  1. What are the predominant colours of the tattoo?
  2. What is the predominant colour of the skin?
  3. What is the area (in pixels) of the tattoo - in the tattoo above, specifically?

I'm new to image processing but my plan of attack is something like:

  1. Run edge detection
  2. Fill in the contours
  3. Take an alpha of that image to just have an alpha of the tattoo
  4. width * height * % of white in alpha = area of tattoo ink
  5. Apply the alpha to the original image and take the colour distribution, to somehow give an answer like "this tattoo has black and red in it"
  6. Invert the alpha and apply it to the original image to get just the skin colour and find the average hue

Does this seem like a sensible approach to get the end result? Is there something easier / more reliable that I might not know, being a novice to this?

I ran some edge analysis code against it using skimage and got a contour like this:

tattoo of woman contour

But I'm having trouble from here to fill in the contour with a colour to create an alpha. The problem is that I only want to know the area of the ink, not of the entire tattoo, so this seems harder to fill in the contour

Upvotes: 3

Views: 1766

Answers (2)

Tonechas
Tonechas

Reputation: 13733

An alternative approach would consist in performing color quantization through k-means clustering. The tattoo shown in the provided example has only one color, therefore the quantized image should have two colors, namely ink and skin.

import numpy as np
from skimage import io
from sklearn.cluster import KMeans

img = io.imread('https://i.sstatic.net/Upcb0.png')
n_colors = 2

X = img.reshape((-1, 3))
kmeans = KMeans(n_clusters=n_colors, random_state=0).fit(X)
labels = kmeans.labels_
centers = kmeans.cluster_centers_
quantized = centers[labels].reshape(img.shape).astype('uint8')

io.imshow(quantized)

tattoo

The RGB coodinates of the predominant colors are:

In [69]: centers
Out[69]: 
array([[ 226.44193236,  193.24337359,  175.1311746 ],
       [  40.0549615 ,   36.64523871,   40.75754915]])

Assuming that the ink is darker than the skin (i.e. the Euclidean norm of the ink color is smaller than that of the skin), the proportion of image pixels covered by the tattoo can be computed like this:

In [70]: darkest = np.argmin(np.sqrt(np.sum(centers**2, axis=1)))

In [71]: np.true_divide(np.sum(labels == darkest), labels.size)
Out[71]: 0.24738437499999999

Upvotes: 1

zeerak
zeerak

Reputation: 398

Instead of using edge detection and contours, I'll suggest the following approch-

1) Convert image from RGB to grayscale.

2) Use adaptive threasholding to convert it into a binary image (I'm suggesting this after looking at the image that you have uploaded).

3) Now simply by counting the number of pixels, you can get the area of tattoo and the skin.

4) To calculate the predominant colors(of which I only see two here), you can either just go for the average of all pixels corresponding to the tattoo and skin from the binary image, or you can compute a color histogram.

Upvotes: 3

Related Questions