Reputation: 802
I have a RAW image that is saved as .dng from a phone's camera. I want to segment the colors with the OpenCV library in Python. The picture is primarily black and green and I want to get the values of the green parts of the image. I've not worked with images in this way and am completely clueless. The tutorial I am following says to convert the image to H.S.V. color space and to use a mask, but I'm running into problems with the mask, if not in other steps. I'm using Google Colabs.
import cv2
import matplotlib.pyplot as plt
import numpy as np
import os
from google.colab import drive
import imageio
import scipy.misc
import skimage.filters
import skimage.metrics
from PIL import Image
# Colabs...
!pip install rawpy
import rawpy
# Colabs...
!pip install ExifRead
import exifread
#image
plate = rawpy.imread('/content/drive/MyDrive/Colab Notebooks/Copy of 0724201706a.dng')
#EXIF
plate_x = open('/content/drive/MyDrive/Colab Notebooks/Copy of 0724201706a.dng', 'rb')
#There are several lines returned. I've left this out for now...
plate_tags = exifread.process_file(plate_x)
plate_tags
plt.imshow(plate.raw_image)
plate_rgb = plate.postprocess( use_camera_wb=True)
plt.imshow(plate_rgb)
plate_rgb.shape
(5312, 2988, 3)
These are a slightly edited RGB, the green channel, and blue channel of the RGB image.
Histograms of the values for each channel in R.G.B. image. The other channels are 0, but green has various values.
I supplied all this info to try to describe the RAW image and the R.G.B.
The tutorial says to convert to the H.S.V. color space. I saw somewhere that the image comes in as B.G.R., so I tried two approaches:
plateRGB_hsv = cv2.cvtColor(plate_rgb, cv2.COLOR_RGB2HSV)
plateBGR_hsv = cv2.cvtColor(plate_rgb, cv2.COLOR_BGR2HSV)
# A lower and upper threshold for mask
hsv_green_lo = (59, 100, 135) #h = 50, s = 100, v = 135)
hsv_green_hi = (75, 250, 255) #h = 75, s = 250, v = 255)
plateRGB_hsv.shape
(5312, 2988, 3)
# Create mask
green_thr = cv2.inRange(plateRGB_hsv, hsv_green_lo, hsv_green_hi)
# Apply mask
img_msk = cv2.bitwise_and(plateRGB_hsv, plateRGB_hsv, green_thr)
plt.subplot(1,2,1)
plt.imshow(green_thr)
plt.subplot(1,2,2)
plt.imshow(img_msk)
plt.show()
Output of the inRange
(mask layer creation) and bitwise_and
(mask application).
rgb_out = cv2.bitwise_and(plate_rgb, plate_rgb, green_thr)
plt.imshow(rgb_out)
plt.plot()
Apply mask and this is output.
So I didn't seem to create the mask properly? And with the bad mask, there was no change when bitwise_and
ran it looks like? I don't know why the mask failed. Is the fact that the R.G.B. or H.S.V. is in three channels complicating the mask and mask application?
The image is here.
EDIT after comments and submitted answer:
I was not clear about what I want my output to look like. I said "green", but really I want it to look like this:
I made a new array with just the green channel as advised.
green_c = plate_rgb[...,1]
But now, I'm confused about how to create a mask. Since the array is just one level, I think of it as a "layer", like in G.I.S. or GIMP, how do I change the unwanted values to black? Sorry if this is obvious. I'm still pretty new to Python.
Upvotes: 0
Views: 949
Reputation: 207650
I am not really sure what you think the problem is. Basically, the Red and Blue channels of your image are empty (look at their mean values in the output below) and you may as well discard them and just use the Green channel as your mask.
#!/usr/bin/env python3
import rawpy
import matplotlib.pyplot as plt
import numpy as np
# Load and process raw DNG
plate = rawpy.imread('raw.dng')
rgb = plate.postprocess()
# Show what we've got
print(f'Dimensions: {rgb.shape}, dtype: {rgb.dtype}')
R = rgb[...,0]
print(f'R channel: min={R.min()}, mean={R.mean()}, max={R.max()}')
G = rgb[...,1]
print(f'G channel: min={G.min()}, mean={G.mean()}, max={G.max()}')
B = rgb[...,2]
print(f'B channel: min={B.min()}, mean={B.mean()}, max={B.max()}')
# Display green channel
plt.imshow(G, cmap='gray')
plt.show()
Output for your image
Dimensions: (5312, 2988, 3), dtype: uint8
R channel: min=0, mean=0.013673103558813567, max=255
G channel: min=0, mean=69.00267554908389, max=255
B channel: min=0, mean=0.017269189710649828, max=255
Keywords: Python, image processing, rawpy, DNG, Adobe DNG format.
Upvotes: 1