Reputation: 33
I am trying to create a program in Python that retrieves webcam footage and applies a slow and constant change in hue, similar to a hue cycling effect. Additionally, I am wondering if it would be possible to apply the hue cycle only to the color green in the webcam footage, though I am unsure how to detect the color in the frame and apply the cycle only to that color.
I have tried playing around with this code I found, though it gets applied to the whole frame and on the output in certain spots discoloration/weird spots depending on the part of the cycle it is on.
import cv2
import numpy as np
# Initialize video capturer
cap = cv2.VideoCapture(0)
# Set frame width and height
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# Initialize angle for hue rotation
angle = 0
while True:
# Capture frame
ret, frame = cap.read()
# Convert frame to HSV color space
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# Split channels
h, s, v = cv2.split(hsv)
# Increment angle
angle = (angle + 1) % 360
# Rotate hue channel
h = (h + angle) % 180
# Merge channels back to HSV image
hsv = cv2.merge((h, s, v))
# Convert back to BGR color space
result = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
# Display frame
cv2.imshow("Webcam", result)
# Check for user input
key = cv2.waitKey(1)
if key == 27: # Esc key
break
# Release video capturer
cap.release()
# Close all windows
cv2.destroyAllWindows()
Upvotes: 2
Views: 113
Reputation: 32124
There is an issue with the expression h = (h + angle) % 180
.
h
type is uint8
, and the range of uint8
elements is [0, 255].
The valid range of hue in OpenCV is [0, 180].
When angle
> 75
, the expression h + angle
may result numerical overflow.
For preventing the overflow we may cast to uint16
, add the angle
, and cast back to uint8
after applying the modulo.
Replace h = (h + angle) % 180
with:
h = ((h.astype(np.uint16) + angle) % 180).astype(np.uint8)
For testing I used an image instead of using a Webcam - it makes the solution more reproducible.
Code sample:
import cv2
import numpy as np
frame = cv2.imread('peppers.png') # Read sample image
cv2.imshow("frame", frame)
# Initialize angle for hue rotation
angle = 0
for i in range(1000):
# Convert frame to HSV color space
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# Split channels
h, s, v = cv2.split(hsv)
# Increment angle
angle = (angle + 1) % 360
# Rotate hue channel
#h = (h + angle) % 180
h = ((h.astype(np.uint16) + angle) % 180).astype(np.uint8)
# Merge channels back to HSV image
hsv = cv2.merge((h, s, v))
# Convert back to BGR color space
result = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
# Display frame
cv2.imshow("Webcam", result)
cv2.waitKey(40)
cv2.destroyAllWindows()
Input image (used for testing):
About applying hue cycle only to the color green, it's not very "well defined".
We may find the green pixels, form a mask, and modify only the non-zero pixels in the mask.
The issue is that there is going to be discontinuity between the pixels that are considered green, and the surrounding pixels that are almost green.
Upvotes: 1
Reputation: 536
You can detect the color green in the frame using color thresholds and a mask. To detect the color green try the inRange function:
import cv2
import numpy as np
# Initialize video capturer
cap = cv2.VideoCapture(0)
# Set frame width and height
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# Initialize angle for hue rotation
angle = 0
while True:
# Capture frame
ret, frame = cap.read()
# Convert frame to HSV color space
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# Split channels
h, s, v = cv2.split(hsv)
# Define lower and upper bounds for green color
lower_green = np.array([50, 50, 50])
upper_green = np.array([70, 255, 255])
# Create mask for green color
mask = cv2.inRange(hsv, lower_green, upper_green)
# Increment angle
angle = (angle + 1) % 360
# Rotate hue channel only for green pixels
h[mask != 0] = (h[mask != 0] + angle) % 180
# Merge channels back to HSV image
hsv = cv2.merge((h, s, v))
# Convert back to BGR color space
result = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
# Display frame
cv2.imshow("Webcam", result)
# Check for user input
key = cv2.waitKey(1)
if key == 27: # Esc key
break
# Release video capturer
cap.release()
# Close all windows
cv2.destroyAllWindows()
Upvotes: 2