How to detect black colour in a video cam using opencv? - python

I need to detect black objects in a real time video. I got a code in the internet for detecting blue objects. So I changed the upper and lower hsv value according to bgr colour code(am not clear about how to convert bgr to hsv), But its not detecting the black object in the video.the code am using blue colour detection is:
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
while(1):
_, frame = cap.read()
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
lower_red = np.array([110,50,50])
upper_red = np.array([130,255,255])
mask = cv2.inRange(hsv, lower_red, upper_red)
res = cv2.bitwise_and(frame,frame, mask= mask)
cv2.imshow('frame',frame)
cv2.imshow('mask',mask)
cv2.imshow('res',res)
k = cv2.waitKey(5) & 0xFF
if k == 27:
break
cv2.destroyAllWindows()
cap.release()
the output for blue color is:
original image:
The code I'm using for black is:`
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
while(1):
_, frame = cap.read()
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
lower_red = np.array([0,0,0])
upper_red = np.array([0,0,0])
mask = cv2.inRange(hsv, lower_red, upper_red)
res = cv2.bitwise_and(frame,frame, mask= mask)
cv2.imshow('frame',frame)
cv2.imshow('mask',mask)
cv2.imshow('res',res)
k = cv2.waitKey(5) & 0xFF
if k == 27:
break
cv2.destroyAllWindows()
cap.release()
Result:
Nothing is displayed in the result of black. I think the problem is in the hsv conversion but am not sure. And in the detected blue image is not at all accurate it result in noise. How to achieve black detection and reduce noise?.

The easiest way to detect black would be to do a binary threshold in greyscale. Black pixel values will always have a very low value, so therefore it would be easier to do this in a 1 channel image instead of a 3 channel. I would recommend:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 15, 255, cv2.THRESH_BINARY_INV)
change the value of 15 until you get reasonable results. Lower value would result in preserving only darker pixels. If you wanted to extract the location of the pixels you could also get the contours i.e.
image, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
and then draw the contour back onto the original frame with:
frame = cv2.drawContours(frame, contours, -1,(0,0,255),3)
Alternatively, you might find it easier to invert the image first so that you are trying to extract white pixels. This could lead to less confusion with the pixels you want to extract being similar to the mask pixel (0). You could do this simple with numpy subtraction, then set your thresh value to a very high value i.e:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = 255-gray
ret, thresh = cv2.threshold(gray, 225, 255, cv2.THRESH_BINARY_INV)
image, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
frame = cv2.drawContours(frame, contours, -1,(0,0,255),3)

black= np.array([0, 0, 0], np.uint8)
grayScale= np.array([0, 0, 29], np.uint8)
Valor (29) depends of how much "brightness" you want.
This page is where you can test your color ranges

Related

How to draw rectangles around every blue object?

I have found lots of information about how to draw rectangles around the biggest blue object in the frame but I need to draw rectangles around all of the blue objects.
This is my current code
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
while True:
_, frame = cap.read()
# Convert BGR to HSV
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# define range of blue color in HSV
lower_blue = np.array([100,50,50])
upper_blue = np.array([130,255,255])
# Threshold the HSV image to get only blue colors
mask = cv2.inRange (hsv, lower_blue, upper_blue)
bluecnts = cv2.findContours(mask.copy(),
cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)[-2]
if len(bluecnts)>0:
blue_area = max(bluecnts, key=cv2.contourArea)
print(blue_area)
(xg,yg,wg,hg) = cv2.boundingRect(blue_area)
cv2.rectangle(frame,(xg,yg),(xg+wg, yg+hg),(0,255,0),2)
result = cv2.bitwise_and(frame, frame, mask=mask)
cv2.imshow('frame',frame)
cv2.imshow('mask',mask)
cv2.imshow('blue', result)
if cv2.waitKey(1) == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
And this is what it currently does, draw one rectangle around the biggest blue object but I need it around each one.
In your Python/OpenCV code, try replacing
if len(bluecnts)>0:
blue_area = max(bluecnts, key=cv2.contourArea)
print(blue_area)
(xg,yg,wg,hg) = cv2.boundingRect(blue_area)
cv2.rectangle(frame,(xg,yg),(xg+wg, yg+hg),(0,255,0),2)
with
if len(bluecnts)>0:
for cnt in bluecnts:
area = cv2.contourArea(cnt)
print(area)
(xg,yg,wg,hg) = cv2.boundingRect(cnt)
cv2.rectangle(frame,(xg,yg),(xg+wg, yg+hg),(0,255,0),2)
(Untested)

Camera not detecting red colour in Python

I'm writing a program to identify red and green colours from the output of a camera, and my camera can't detect red colours. I've tried changing the red values but it still doesn't seem to work. Does anyone know where I went wrong? Thank you!
import numpy as np
import cv2
red_lower = np.array([156,43,46])
red_upper = np.array([180,255,255])#这里是设置颜色
green_lower=np.array([35,43,46])
green_lower=np.array([77,255,255])
cap = cv2.VideoCapture(0)
cap.set(3, 320)
cap.set(4, 240)
while 1:
ret, frame = cap.read()
frame = cv2.GaussianBlur(frame, (5, 5), 0)
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, red_lower, red_upper)
mask = cv2.inRange(hsv, green_lower, green_upper)
# 图像学膨胀腐蚀
mask = cv2.erode(mask, None, iterations=2)
mask = cv2.GaussianBlur(mask, (3, 3), 0)
res = cv2.bitwise_and(frame, frame, mask=mask)
# 寻找轮廓并绘制轮廓
cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]
if len(cnts) > 0:
# 寻找面积最大的轮廓并画出其最小外接圆
cnt = max(cnts, key=cv2.contourArea)
(x, y), radius = cv2.minEnclosingCircle(cnt)
cv2.circle(frame, (int(x), int(y)), int(radius), (255, 0, 255), 2)
# 找到物体的位置坐标,获得颜色物体的位置,可以来控制小车的转向
print(int(x), int(y))
else:
pass
cv2.imshow('frame', frame)
cv2.imshow('mask', mask)
cv2.imshow('res', res)
if cv2.waitKey(5) & 0xFF == 27:
break
cap.release()
cv2.destroyAllWindows()
Error codes are as follows:
Redeclared 'mask' defined above without usage
your code says
red_lower = np.array([156,43,46])
red_upper = np.array([180,255,255])
that means you only consider hue "angles" of 312 to 360 degrees, which is red with a touch of magenta.
red is defined to be around angle 0.
what about angles on the positive side of 0 degrees, red with a touch of yellow?
you'll need to widen your range of hues. you'll need to define another two bounds to catch hues on the positive side of 0 degrees, then use a "bitwise or" operation to combine both ranges of red into one mask.
(if you found this answer useful, please accept and vote on it. thanks!)
"Redeclared 'mask' defined above without usage" is not an error, but it's a hint your IDE is giving as to what's going wrong here.
The second line in
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, red_lower, red_upper)
mask = cv2.inRange(hsv, green_lower, green_upper)
practically does nothing since you immediately reassign mask = afterwards.
If you want to combine two masks, you could use bitwise_or:
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
red_mask = cv2.inRange(hsv, red_lower, red_upper)
green_mask = cv2.inRange(hsv, green_lower, green_upper)
mask = cv2.bitwise_or(red_mask, green_mask)

Python OpenCV: Change background color to white

Can anyone share the code for changing the background color of attached image to white, so that I can recognize the foreground the digits with OCR software?
You need to convert to gray, apply contrast and use threshold to get this result:
import cv2
import numpy as np
img = cv2.imread("digits.jpg", cv2.IMREAD_COLOR)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)[...,0]
# edges = cv2.Canny(gray, 10,30)
blurred = cv2.GaussianBlur(gray, (7, 7), 0)
clahe = cv2.createCLAHE(clipLimit=5.0, tileGridSize=(32,32))
contrast = clahe.apply(blurred)
ret, thresh = cv2.threshold(contrast, 20, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)
while True:
cv2.imshow("result", thresh)
k = cv2.waitKey(30) & 0xff
if k == 27:
break

Analyze an image in specific area and determine if it's red using Opencv Python

I'm using Opencv python in raspberry pi, to analize a heatmap, i'm looking for color red, which represents the highest temperature, i need to detect if in an specific area exist red color, in case it does i can use this information to activate a condition, i'm using a heatmap like this:
for the red color detection i'm using this code:
import cv2
import numpy as np
while(1):
# Take each frame
frame = cv2.imread('heatmap.png')
# Convert BGR to HSV
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# define range of blue color in HSV
lower_red = np.array([-20, 100, 100])
upper_red = np.array([13, 255, 255])
# Threshold the HSV image to get only blue colors
mask = cv2.inRange(hsv, lower_red, upper_red)
# Bitwise-AND mask and original image
res = cv2.bitwise_and(frame,frame, mask= mask)
cv2.imshow('heatmap',frame)
cv2.imshow('mask',mask)
cv2.imshow('res',res)
k = cv2.waitKey(5) & 0xFF
if k == 27:
break
cv2.destroyAllWindows()
the code above give me al the pixels in red, but i need to determine if the heatmap contour is red, i mean the image contour or border would be a red color not permited area, does anyone how i can do that?
Your HSV range is not right. For red, (0,20,20)~(8,255,255), (170,20,20) ~ (180,255,255).
Here is my result:
The code:
#!/usr/bin/python3
# 2018/05/16 13:54:09
import cv2
import numpy as np
img = cv2.imread('heatmap.png')
# Convert BGR to HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
mask1 = cv2.inRange(hsv, (0,20,20), (8,255,255))
mask2 = cv2.inRange(hsv, (170,20,20), (180,255,255))
mask = cv2.bitwise_or(mask1, mask2)
dst = cv2.bitwise_and(img, img, mask=mask)
cv2.imshow("dst", dst)
cv2.imwrite("__.png", dst)
cv2.waitKey()
Some useful links:
Choosing the correct upper and lower HSV boundaries for color detection with`cv::inRange` (OpenCV)
How to define a threshold value to detect only green colour objects in an image :Opencv

Detecting Red and Blue Squares (beanbags) using Python and CV2

I am new to CV2 and I am looking for some high level guidance for an application. I am working on a program that can detect red and blue beanbags that are in the frame of the camera. I played around with the example code offered by openCV to detect blue colors and modified it slightly to detect red as well.
import cv2
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
cap = cv2.VideoCapture(0)
while(1):
# Take each frame
_, frame = cap.read()
# Convert BGR to HSV
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# define range of blue color in HSV
lower_blue = np.array([110,50,50])
upper_blue = np.array([130,255,255])
lower_red = np.array([-20, 100, 100])
upper_red = np.array([13, 255, 255])
# Threshold the HSV image to get only blue colors
mask = cv2.inRange(hsv, lower_red, upper_red)
# Bitwise-AND mask and original image
res = cv2.bitwise_and(frame,frame, mask= mask)
cv2.imshow('frame',frame)
cv2.imshow('mask',mask)
cv2.imshow('res',res)
k = cv2.waitKey(5) & 0xFF
if k == 27:
break
cv2.destroyAllWindows()
This is (slightly modified) copied and pasted code from the OpenCV site. I am looking for the correct way to analyze the res numpy array of the dimensions <460, 640, 3> in order to detect that
I have red/blue objects(s) on my screen
Do something with this information such as print(1 red and 2 blue squares detected)
Image link:
Input, res and mask image of blue beanbag
You will need to obtain two masks, one for red and the other for blue as:
mask_red = cv2.inRange(hsv, lower_red, upper_red)
mask_blue = cv2.inRange(hsv, lower_blue, upper_blue)
Now let's define a function which detects if given area in mask if above threshold for taking decision if the bean bags are present, for that purpose we will use cv2.findContours.
def is_object_present(mask, threshold):
im, contours, hierarchy = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
# Find the largest contour
largest_contour = max(contours, key=lambda x:cv2.contourArea(x))
if cv2.contourArea(largest_contour) > threshold:
return True
return False
Now you call this method on both the masks, to get individual values if red bean bag or blue bean bag is present:
# Adjust this manually as per your needs
bean_bag_area_threshold = 5000
is_red_bean_bag_present = is_object_present(mask_red, bean_bag_area_threshold)
is_blue_bean_bag_present = is_object_present(mask_blue, bean_bag_area_threshold)
if is_red_bean_bag_present and is_blue_bean_bag_present:
print "Both bean bags are present."

Categories

Resources