user2115620
user2115620

Reputation: 111

What is the best approach for isolating a single area of similar colour?

I have a satellite image and am trying to isolate one roof based on it's color. My plan is to take the color of a chosen point in the image, and create a slightly lighter > slightly darker range from it (allowing for variation based on sun and shade) and to remove all colors other than those within the range.

Then I need to keep only the color area that contains the originally selected point.

Below is an example sample image, color range and final image I would like to achieve edited manually in photoshop.

I have also had trouble converting an RGB color to HSV values that produce predictable results in the following script. I have tried following various guides for green-screening using python, e.g: this and this.

I have been trying to use the following but am running into a few issues:

img = cv2.imread("static.jpg".format(latlon, zoom))
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# light color in RGB = [153, 139, 130]
# dark color in RGB = [82, 74, 71]
# How to convert these to HSV?
# using 150,0,0 here as it creates a valid range
hsv_color1 = np.array([150,0,0])

# using 180,255,255 here as it creates a valid range
hsv_color2 = np.array([180,255,255])
mask = cv2.inRange(img_hsv, hsv_color1, hsv_color2)
res = cv2.bitwise_and(img, img, mask = mask)
cv2.imshow('mask', mask)
cv2.imwrite("mask.jpg".format(latlon, zoom), mask)
cv2.imshow('img_hsv', img_hsv)
cv2.imwrite("img_hsv.jpg".format(latlon, zoom), img_hsv)
cv2.imshow('res', res)
cv2.imwrite("res.png".format(latlon, zoom), res)

So my 2 questions are:

  1. How to convert RGB to HSV values that will create a valid inRange to isolate these colours?
  2. How to only one area of inRange colour based on a given pixel position?
  3. And for a bonus point, how to make the mask for the isolated inRange area a nice tight mask?

I need to output an image that isolates the color area around a given pixel position.

Original ORIGINAL

Desired Output DESIRED OUTPUT

Light colour LIGHT COLOR

Dark colour DARK COLOR

Upvotes: 2

Views: 206

Answers (1)

Mark Setchell
Mark Setchell

Reputation: 207345

Your dark value becomes 16/13/32 in HSV. And your light value becomes 23/14/60 in HSV.

OpenCV scales the Hue values by dividing by 2 so that the full range of 360 becomes 180 and still fits into an unsigned 8-bit number. So, you need to use a dark Hue value of 8 and a light Hue value of 12. I would widen that range by 3-5 at each end to allow some leeway, and use a lowish saturation to only pick up unsaturated, greyish values. So the code becomes:

#!/usr/bin/env python3

import cv2
import numpy as np

img = cv2.imread("static.jpg")
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# light color in RGB = [153, 139, 130]
# dark color in RGB = [82, 74, 71]

hsv_lo = np.array([5,0,0])
hsv_hi = np.array([15,50,255])
mask = cv2.inRange(img_hsv, hsv_lo, hsv_hi)
res = cv2.bitwise_and(img, img, mask = mask)
cv2.imwrite("result.png", res)

enter image description here

Upvotes: 2

Related Questions