20

I am working on an image processing feature extraction. I have a photo of a bird in which I have to extract bird area and tell what color the bird has. I used canny feature extraction method to get the edges of a bird.

How to extract only bird area and make the background to blue color?

openCv solution should also be fine.

enter image description here

import skimage
import numpy as np
%matplotlib inline
import matplotlib.pyplot as plt

import os
filename = os.path.join(os.getcwd(),'image\image_bird.jpeg')
from skimage import io
bird =io.imread(filename,as_grey=True)
plt.imshow(bird)

enter image description here

from skimage import feature
edges = feature.canny(bird,sigma=1)
plt.imshow(edges )

enter image description here

Actual bird image can be taken from bird link

Sumeet Kumar Yadav
  • 11,912
  • 6
  • 43
  • 80

2 Answers2

23
  1. Identify the edges of your imageSobel edge map

  2. Binarize the image via automatic thresholdingbinarized edge map

  3. Use contour detection to identify black regions which are inside a white region and merge them with the white region. (Mockup, image may slightly vary) Mockup of the merged mask

  4. Use the created image as mask to color the background and color it final image This can be done by simply setting each background pixel (black) to its respective color.

As you can see, the approach is far from perfect, but should give you a general idea about how to accomplish your task. The final image quality might be improved by slightly eroding the map to tighten it to the contours of the bird. You then also use the mask to calculate your color histogram by only taking foreground pixels into account. Edit: Look here:

  1. Eroded mask

eroded mask

  1. Final image

Final image with eroded mask

SilverMonkey
  • 1,003
  • 7
  • 16
  • I am reading OpenCV and starting from step-1 , can you help me with some sample code to start with . – Sumeet Kumar Yadav Sep 04 '18 at 15:50
  • I personally do not use OpenCV, so i could only gather the respective methods for each step. – SilverMonkey Sep 06 '18 at 16:54
  • 1
    Pretty good answer to an under-specified question I think. Bearing in mind that identifying and segmenting a bird in a photo is very, very difficult, so this method pretty much takes the histogram of whatever object(s) are in focus, bird or not. If that's not good enough for the OP, they need to rephrase the question. – Chungzuwalla Sep 07 '18 at 00:50
  • This explanation is nice, I am reading opencv and trying now . If some one knows opencv can post with code – Sumeet Kumar Yadav Sep 07 '18 at 04:18
7

According to this article https://www.pyimagesearch.com/2016/04/11/finding-extreme-points-in-contours-with-opencv/ and this question CV - Extract differences between two images

I wrote some python code as below. As my predecessor said it is also far from perfect. The main disadvantages of this code are constants value to set manually: minThres (50), maxThres(100), dilate iteration count and erode iteration count.

import cv2
import numpy as np

windowName = "Edges"
pictureRaw = cv2.imread("bird.jpg")

## set to gray
pictureGray = cv2.cvtColor(pictureRaw,  cv2.COLOR_BGR2GRAY)

## blur
pictureGaussian = cv2.GaussianBlur(pictureGray, (7,7), 0)

## canny edge detector - you must specify threshold values
pictureCanny = cv2.Canny(pictureGaussian, 50, 100)

## perform a series of erosions + dilations to remove any small regions of noise
pictureDilate = cv2.dilate(pictureCanny, None, iterations=20)
pictureErode = cv2.erode(pictureDilate, None, iterations=5)

## find the nozero regions in the erode
imask2 = pictureErode>0

## create a Mat like pictureRaw
canvas = np.full_like(pictureRaw, np.array([255,0,0]), dtype=np.uint8)

## set mask 
canvas[imask2] = pictureRaw[imask2]
cv2.imwrite("result.png", canvas)
ElConrado
  • 1,477
  • 4
  • 20
  • 46