I'm trying to do a sorting machine for color detection with a camera and a raspberry pi. I have succeeded to some extent but not really. I am currently reading the color from the center pixel in BGR format and examining it that way. My question would be how can i read this out of a zone not just a point and make the detection more accurate.
Here's my code:
import cv2
import time
import pandas as pd
index = ["color", "color_name", "hex", "R", "G", "B"]
csv = pd.read_csv('colors.csv', names=index, header=None)
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 800)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 600)
def get_color_name(R, G, B):
minimum = 10000
for i in range(len(csv)):
d = abs(R - int(csv.loc[i, "R"])) abs(G - int(csv.loc[i, "G"])) abs(B - int(csv.loc[i, "B"]))
if d <= minimum:
minimum = d
cname = csv.loc[i, "color_name"]
return cname
while True:
_, frame = cap.read()
height, width, _ = frame.shape
cx = int(width / 2)
cy = int(height / 2)
pixel_center = frame[cy, cx]
b = int(pixel_center[0])
g = int(pixel_center[1])
r = int(pixel_center[2])
txt = get_color_name(r, g, b)
print(txt)
print(r, g, b)
cv2.circle(frame, (cx, cy), 5, (255, 0, 0), 3)
cv2.imshow("Frame", frame)
key = cv2.waitKey(1)
if key == 27:
break
cap.release()
cv2.destroyAllWindows()
Can anyone help?
CodePudding user response:
Why not try something like this:
The image you captured is now a 2D array, slice it from the center, and read a bunch of points representing a small rectangle in the center. Then, you can average them or get the median, it is up to you.
# capture a video frame here
height, width, _ = frame.shape
zone_width = 15
zone_height = 15
frame_center = (frame.shape[0] / 2, frame.shape[1] / 2)
y1 = int(frame_center[0] - zone_height)
y2 = int(frame_center[0] zone_height)
x1= int(frame_center[1] - zone_width)
x2 = int(frame_center[1] zone_width)
selection = frame[y1:y2, x1:x2]
r, g, b = get_avg_color()