Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 124 additions & 0 deletions plantcv/plantcv/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -457,3 +457,127 @@ def _grayscale_to_rgb(img):
img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)

return img


def _rgb2lab(rgb_img, channel):
"""Convert image from RGB colorspace to LAB colorspace. Returns the specified subchannel as a gray image.

Parameters
----------
rgb_img : numpy.ndarray
RGB image data
channel : str
color subchannel (l = lightness, a = green-magenta, b = blue-yellow)

Returns
-------
numpy.ndarray
grayscale image from one LAB color channel
"""
# The allowable channel inputs are l, a or b
channel = channel.lower()
if channel not in ["l", "a", "b"]:
fatal_error("Channel " + str(channel) + " is not l, a or b!")

# Convert the input BGR image to LAB colorspace
lab = cv2.cvtColor(rgb_img, cv2.COLOR_BGR2LAB)
# Split LAB channels
l, a, b = cv2.split(lab)
# Create a channel dictionaries for lookups by a channel name index
channels = {"l": l, "a": a, "b": b}
return channels[channel]


def _rgb2hsv(rgb_img, channel):
"""Convert image from RGB colorspace to HSV colorspace. Returns the specified subchannel as a gray image.

Parameters
----------
rgb_img : numpy.ndarray
RGB image data
channel : str
color subchannel (h = hue, s = saturation, v = value/intensity/brightness)

Returns
-------
numpy.ndarray
grayscale image from one HSV color channel
"""
# The allowable channel inputs are h, s or v
channel = channel.lower()
if channel not in ["h", "s", "v"]:
fatal_error("Channel " + str(channel) + " is not h, s or v!")

# Convert the input BGR image to HSV colorspace
hsv = cv2.cvtColor(rgb_img, cv2.COLOR_BGR2HSV)
# Split HSV channels
h, s, v = cv2.split(hsv)
# Create a channel dictionaries for lookups by a channel name index
channels = {"h": h, "s": s, "v": v}

return channels[channel]


def _rgb2cmyk(rgb_img, channel):
"""Convert image from RGB colorspace to CMYK colorspace. Returns the specified subchannel as a gray image.

Parameters
----------
rgb_img : numpy.ndarray
RGB image data
channel : str
color subchannel (c = cyan, m = magenta, y = yellow, k=black)

Returns
-------
numpy.ndarray
grayscale image from one CMYK color channel
"""
# Set NumPy to ignore divide by zero errors
_ = np.seterr(divide='ignore', invalid='ignore')
# The allowable channel inputs are c, m , y or k
channel = channel.lower()
if channel not in ["c", "m", "y", "k"]:
fatal_error("Channel " + str(channel) + " is not c, m, y or k!")

# Create float
bgr = rgb_img.astype(float)/255.

# K channel
k = 1 - np.max(bgr, axis=2)

# C Channel
c = (1 - bgr[..., 2] - k) / (1 - k)

# M Channel
m = (1 - bgr[..., 1] - k) / (1 - k)

# Y Channel
y = (1 - bgr[..., 0] - k) / (1 - k)

# Convert the input BGR image to LAB colorspace
cmyk = (np.dstack((c, m, y, k)) * 255).astype(np.uint8)
# Split CMYK channels
y, m, c, k = cv2.split(cmyk)
# Create a channel dictionaries for lookups by a channel name index
channels = {"c": c, "m": m, "y": y, "k": k}

return channels[channel]


def _rgb2gray(rgb_img):
"""Convert image from RGB colorspace to Gray.

Parameters
----------
rgb_img : numpy.ndarray
RGB image data

Returns
-------
numpy.ndarray
grayscale image
"""
gray = cv2.cvtColor(rgb_img, cv2.COLOR_BGR2GRAY)

return gray
6 changes: 3 additions & 3 deletions plantcv/plantcv/report_size_marker_area.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
import cv2
import numpy as np
import os
from plantcv.plantcv import params, outputs, fatal_error, apply_mask, rgb2gray_hsv
from plantcv.plantcv import params, outputs, fatal_error, apply_mask
from plantcv.plantcv.threshold import binary as binary_threshold
from plantcv.plantcv._debug import _debug
from plantcv.plantcv._helpers import _cv2_findcontours, _object_composition, _roi_filter
from plantcv.plantcv._helpers import _cv2_findcontours, _object_composition, _roi_filter, _rgb2hsv


def report_size_marker_area(img, roi, marker='define', objcolor='dark', thresh_channel=None,
Expand Down Expand Up @@ -66,7 +66,7 @@ def report_size_marker_area(img, roi, marker='define', objcolor='dark', thresh_c
# Mask the input image
masked = apply_mask(img=ref_img, mask=roi_mask, mask_color="black")
# Convert the masked image to hue, saturation, or value
marker_hsv = rgb2gray_hsv(rgb_img=masked, channel=thresh_channel)
marker_hsv = _rgb2hsv(rgb_img=masked, channel=thresh_channel)
# Threshold the HSV image
marker_bin = binary_threshold(gray_img=marker_hsv, threshold=thresh, object_type=objcolor)
# Identify contours in the masked image
Expand Down
21 changes: 11 additions & 10 deletions plantcv/plantcv/rgb2gray.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
# RGB -> Gray

import cv2
import os
from plantcv.plantcv import params
from plantcv.plantcv._debug import _debug
from plantcv.plantcv._helpers import _rgb2gray


def rgb2gray(rgb_img):
"""Convert image from RGB colorspace to Gray.

Inputs:
rgb_img = RGB image data
Parameters
----------
rgb_img : numpy.ndarray
RGB image data

Returns:
gray = grayscale image

:param rgb_img: numpy.ndarray
:return gray: numpy.ndarray
Returns
-------
numpy.ndarray
grayscale image
"""
gray = cv2.cvtColor(rgb_img, cv2.COLOR_BGR2GRAY)
gray = _rgb2gray(rgb_img=rgb_img)

_debug(visual=gray, filename=os.path.join(params.debug_outdir, str(params.device) + "_gray.png"))
_debug(visual=gray, filename=os.path.join(params.debug_outdir, f"{params.device}_gray.png"))

return gray
61 changes: 18 additions & 43 deletions plantcv/plantcv/rgb2gray_cmyk.py
Original file line number Diff line number Diff line change
@@ -1,59 +1,34 @@
"""Convert RGB to CMYK colorspace and return the specified subchannel as a grayscale image."""

import cv2
import os
from plantcv.plantcv._debug import _debug
from plantcv.plantcv import fatal_error
from plantcv.plantcv import params
import numpy as np
from plantcv.plantcv._helpers import _rgb2cmyk


def rgb2gray_cmyk(rgb_img, channel):
"""Convert image from RGB colorspace to CMYK colorspace. Returns the specified subchannel as a gray image.

Inputs:
rgb_img = RGB image data
channel = color subchannel (c = cyan, m = magenta, y = yellow, k=black)

Returns:
c | m | y | k = grayscale image from one CMYK color channel

:param rgb_img: numpy.ndarray
:param channel: str
:return channel: numpy.ndarray
Parameters
----------
rgb_img : numpy.ndarray
RGB image data
channel : str
color subchannel (c = cyan, m = magenta, y = yellow, k=black)

Returns
-------
numpy.ndarray
grayscale image from one CMYK color channel
"""
# Set NumPy to ignore divide by zero errors
_ = np.seterr(divide='ignore', invalid='ignore')
# Convert RGB to CMYK and return the specified subchannel as a gray image
gray_img = _rgb2cmyk(rgb_img=rgb_img, channel=channel)

# The allowable channel inputs are c, m , y or k
names = {"c": "cyan", "m": "magenta", "y": "yellow", "k": "black"}
channel = channel.lower()
if channel not in names:
fatal_error("Channel " + str(channel) + " is not c, m, y or k!")

# Create float
bgr = rgb_img.astype(float)/255.

# K channel
k = 1 - np.max(bgr, axis=2)

# C Channel
c = (1 - bgr[..., 2] - k) / (1 - k)

# M Channel
m = (1 - bgr[..., 1] - k) / (1 - k)

# Y Channel
y = (1 - bgr[..., 0] - k) / (1 - k)

# Convert the input BGR image to LAB colorspace
cmyk = (np.dstack((c, m, y, k)) * 255).astype(np.uint8)
# Split CMYK channels
y, m, c, k = cv2.split(cmyk)
# Create a channel dictionaries for lookups by a channel name index
channels = {"c": c, "m": m, "y": y, "k": k}

# Save or display the grayscale image
_debug(visual=channels[channel], filename=os.path.join(params.debug_outdir,
str(params.device) + "_cmyk_" + names[channel] + ".png"))
_debug(visual=gray_img,
filename=os.path.join(params.debug_outdir, f"{params.device}_cmyk_{names[channel.lower()]}.png"), cmap="gray")

return channels[channel]
return gray_img
52 changes: 21 additions & 31 deletions plantcv/plantcv/rgb2gray_hsv.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,33 @@
# RGB -> HSV -> Gray

import cv2
import os
from plantcv.plantcv._debug import _debug
from plantcv.plantcv import fatal_error
from plantcv.plantcv import params
from plantcv.plantcv._helpers import _rgb2hsv


def rgb2gray_hsv(rgb_img, channel):
"""Convert image from RGB colorspace to HSV colorspace. Returns the specified subchannel as a gray image.

Parameters
----------
rgb_img : numpy.ndarray
RGB image data
channel : str
color subchannel (h = hue, s = saturation, v = value/intensity/brightness)

Returns
-------
numpy.ndarray
grayscale image from one HSV color channel
"""
Convert an RGB color image to HSV colorspace and return a gray image (one channel).
# Convert RGB to HSV and return the specified subchannel as a gray image
gray_img = _rgb2hsv(rgb_img=rgb_img, channel=channel)

Inputs:
rgb_img = RGB image data
channel = color subchannel (h = hue, s = saturation, v = value/intensity/brightness)

Returns:
h | s | v = image from single HSV channel

:param rgb_img: numpy.ndarray
:param channel: str
:return channel: numpy.ndarray
"""
# The allowable channel inputs are h, s or v
names = {"h": "hue", "s": "saturation", "v": "value"}
channel = channel.lower()
if channel not in names:
fatal_error("Channel " + str(channel) + " is not h, s or v!")

# Convert the input BGR image to HSV colorspace
hsv = cv2.cvtColor(rgb_img, cv2.COLOR_BGR2HSV)
# Split HSV channels
h, s, v = cv2.split(hsv)
# Create a channel dictionaries for lookups by a channel name index
channels = {"h": h, "s": s, "v": v}

_debug(visual=channels[channel],
filename=os.path.join(params.debug_outdir,
str(params.device) + "_hsv_" + names[channel] + ".png"),
cmap='gray')

return channels[channel]

_debug(visual=gray_img,
filename=os.path.join(params.debug_outdir, f"{params.device}_hsv_{names[channel.lower()]}.png"), cmap='gray')

return gray_img
53 changes: 22 additions & 31 deletions plantcv/plantcv/rgb2gray_lab.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,34 @@
# RGB -> LAB -> Gray

import cv2
import os
from plantcv.plantcv._debug import _debug
from plantcv.plantcv import fatal_error
from plantcv.plantcv import params
from plantcv.plantcv._helpers import _rgb2lab


def rgb2gray_lab(rgb_img, channel):
"""Convert image from RGB colorspace to LAB colorspace. Returns the specified subchannel as a gray image.

Parameters
----------
rgb_img : numpy.ndarray
RGB image data
channel : str
color subchannel (l = lightness, a = green-magenta, b = blue-yellow)

Returns
-------
numpy.ndarray
grayscale image from one LAB color channel
"""
Convert image from RGB colorspace to LAB colorspace. Returns the specified subchannel as a gray image.
# Convert RGB to LAB and return the specified subchannel as a gray image
gray_img = _rgb2lab(rgb_img=rgb_img, channel=channel)

Inputs:
rgb_img = RGB image data
channel = color subchannel (l = lightness, a = green-magenta, b = blue-yellow)

Returns:
l | a | b = grayscale image from one LAB color channel

:param rgb_img: numpy.ndarray
:param channel: str
:return channel: numpy.ndarray
"""
# The allowable channel inputs are l, a or b
names = {"l": "lightness", "a": "green-magenta", "b": "blue-yellow"}
channel = channel.lower()
if channel not in names:
fatal_error("Channel " + str(channel) + " is not l, a or b!")

# Convert the input BGR image to LAB colorspace
lab = cv2.cvtColor(rgb_img, cv2.COLOR_BGR2LAB)
# Split LAB channels
l, a, b = cv2.split(lab)
# Create a channel dictionaries for lookups by a channel name index
channels = {"l": l, "a": a, "b": b}

_debug(visual=channels[channel],
filename=os.path.join(params.debug_outdir,
str(params.device) + "_lab_" + names[channel] + ".png"),
cmap="gray")

return channels[channel]

# Display debug image
_debug(visual=gray_img,
filename=os.path.join(params.debug_outdir, f"{params.device}_lab_{names[channel.lower()]}.png"), cmap="gray")

return gray_img
Loading