im trying to make a color detection system with python opencv this is what i have done so far. im still new to python so please help me thank you
basically what should happen is that when the user opens this application the camera open and when he clicks anywhere on the window it will tell the name of the color
from tkinter import *
from tkinter import ttk
import cv2
import numpy as np
import webcolors
def click_event(event, x, y, flags, param):
if event == cv2.EVENT_LBUTTONDOWN:
blue = cap[y, x, 0]
green = cap[y, x, 1]
red = cap[y, x, 2]
font = cv2.FONT_HERSHEY_SIMPLEX
#colourcode = str(blue) + ", " + str(green) + ", " + str(red)
colourcode2 = (red, green, blue)
cv2.imshow('frame', frame)
def closest_colour(requested_colour):
min_colours = {}
for key, name in webcolors.css3_hex_to_names.items():
r_c, g_c, b_c = webcolors.hex_to_rgb(key)
rd = (r_c - requested_colour[0]) ** 2
gd = (g_c - requested_colour[1]) ** 2
bd = (b_c - requested_colour[2]) ** 2
min_colours[(rd + gd + bd)] = name
return min_colours[min(min_colours.keys())]
def get_colour_name(requested_colour):
try:
closest_name = actual_name = webcolors.rgb_to_name(requested_colour)
except ValueError:
closest_name = closest_colour(requested_colour)
actual_name = None
return actual_name, closest_name
#print(colourcode2)
requested_colour = colourcode2
actual_name, closest_name = get_colour_name(requested_colour)
#print("colour name:", closest_name)
cv2.putText(img, closest_name, (0, 50), font, 1, 255, 2)
cap = cv2.VideoCapture(0);
while True:
ret, frame = cap.read()
cv2.imshow('frame', frame)
if cv2.waitKey(40) == 27:
break
cv2.waitKey(0)
cv2.destroyAllWindows()
I don't know what is your problem but using your code I create version which works for me
I use cv2.setMouseCallback to assign your function to mouse click. It gets pixel from frame, not cap. Pixel is a list/tuple of (B,G,R) so I revere it list[::-1]. After I get name of color I assign it to external/global variable, not put on frame. In main loop I use this name to put on frame before it will display it.
I also use EVENT_LBUTTONUP to remove text when I release mouse button.
elif event == cv2.EVENT_LBUTTONUP:
closest_name = ''
If you remove above lines then it will keep text when you release mouse button.
import cv2
import webcolors
# --- functions ---
def closest_colour(requested_colour):
min_colours = {}
for key, name in webcolors.css3_hex_to_names.items():
r_c, g_c, b_c = webcolors.hex_to_rgb(key)
rd = (r_c - requested_colour[0]) ** 2
gd = (g_c - requested_colour[1]) ** 2
bd = (b_c - requested_colour[2]) ** 2
min_colours[(rd + gd + bd)] = name
return min_colours[min(min_colours.keys())]
def get_colour_name(requested_colour):
try:
closest_name = actual_name = webcolors.rgb_to_name(requested_colour)
except ValueError:
closest_name = closest_colour(requested_colour)
actual_name = None
return actual_name, closest_name
def click_event(event, x, y, flags, param):
global closest_name # inform function to assign to global/external variable instead of creating local one
if event == cv2.EVENT_LBUTTONDOWN:
#B, G, R = frame[x, y]
#colour = (R, G, B) # reverse values
colour = frame[y,x][::-1] # reverse values
actual_name, closest_name = get_colour_name(colour)
print(actual_name, closest_name)
elif event == cv2.EVENT_LBUTTONUP:
closest_name = ''
# --- main ---
font = cv2.FONT_HERSHEY_SIMPLEX
closest_name = '' # create global variable at start
cap = cv2.VideoCapture(0);
cv2.namedWindow('frame')
cv2.setMouseCallback('frame', click_event)
while True:
ret, frame = cap.read()
if closest_name:
#print(closest_name)
cv2.putText(frame, closest_name, (10, 30), font, 1, (255,255,255), 2)
cv2.imshow('frame', frame)
if cv2.waitKey(40) == 27:
break
cv2.waitKey(0)
cv2.destroyAllWindows()
cap.release()
In all GUIs when you press button then it creates single event EVENT_LBUTTONDOWN - it doesn't generate it again and again when you keep button pressed. So function click_event is executed only once and your version puts text only on one frame but few miliseconds later main loop gets new frame and displays it without text - so finally you don't see text on frame.
Related
The issue to show the webcam in the window from pyqt5, it shows in the external window
we tried this code:
class FacialRecSt(QDialog):
def init(self):
super(FacialRecSt, self).init()
loadUi("FacialRecSetup.ui",self)
self.ExitFacialSetUp.clicked.connect(self.gotoExitFacialSetUp)
self.TakeMyAttendanceButton.clicked.connect(self.startVideo)
#FacialRecSt.displayImage()
now = QDate.currentDate()
current_date = now.toString('ddd dd MMMM yyyy') #format of date
current_time = datetime.datetime.now().strftime("%I:%M %p") #for time,p: pm or am
self.Date_Output.setText(current_date)
self.Time_Output.setText(current_time)
self.img = None
#exit
def gotoExitFacialSetUp(self):
widget.setCurrentIndex(widget.currentIndex()-14)
def startVideo(self):
path = 'Dataset'
images = []
classNames = []
myList = os.listdir(path)
print(myList)
for cl in myList:
curImg = cv2.imread(f'{path}/{cl}')
images.append(curImg)
classNames.append(os.path.splitext(cl)[0]) #to show only bame without .jpg
print(classNames)
self.timer = QTimer(self) # Create Timer
self.timer.timeout.connect(self.update_frame) # Connect timeout to the output function
self.timer.start(10) # emit the timeout() signal at x=40ms
#find encoding foe each image
def findEncodings(images):
encodeList = []
for img in images:
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
encode = face_recognition.face_encodings(img)[0]
encodeList.append(encode)
return encodeList
def mark_attendance(name):
#To not click the button multiple times
if self.TakeMyAttendanceButton.isChecked():
self.TakeMyAttendanceButton.setEnabled(False)
with open('attendanceName.csv', 'a') as f:
if (name != 'unknown'): #if name in database.
#if they press clicking take my attendance by mistake, default here is no
buttonReply = QMessageBox.question(self, 'Welcome ' + name, 'Are you pressing "Taking My Attendance"?' ,
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
#When Answer is yes
#if the button not clocked by mistake, answer yes
if buttonReply == QMessageBox.Yes:
date_time_string = datetime.datetime.now().strftime("%y/%m/%d %H:%M:%S")
f.writelines(f'\n{name},{date_time_string}')
self.TakeMyAttendanceButton.setChecked(False)
self.Name_Output.setText(name)
self.Time_Output = datetime.datetime.now()
self.TakeMyAttendanceButton.setEnabled(True)
# When answer is NO show:
else:
print('Button is Not clicked.')
self.TakeMyAttendanceButton.setEnabled(True)
#### FOR CAPTURING SCREEN RATHER THAN WEBCAM
# def captureScreen(bbox=(300,300,690+300,530+300)):
# capScr = np.array(ImageGrab.grab(bbox))
# capScr = cv2.cvtColor(capScr, cv2.COLOR_RGB2BGR)
# return capScr
encodeListKnown = findEncodings(images)
print('Encoding Complete')
cap = cv2.VideoCapture(0)
while True:
success, img = cap.read()
#img = cv2.captureScreen()
imgS = cv2.resize(img,(0,0),None,0.25,0.25)
imgS = cv2.cvtColor(imgS, cv2.COLOR_BGR2RGB)
facesCurFrame = face_recognition.face_locations(imgS) #find lcation of face even from multiple faces in image
encodesCurFrame = face_recognition.face_encodings(imgS,facesCurFrame)
#loop through all faces, zip to be in same loop
for encodeFace,faceLoc in zip(encodesCurFrame,facesCurFrame):
matches = face_recognition.compare_faces(encodeListKnown,encodeFace)
faceDis = face_recognition.face_distance(encodeListKnown,encodeFace)#face distance for each one, lowest distance is best match
#print(faceDis)
matchIndex = np.argmin(faceDis) #min distance in face
#name for the person
if matches[matchIndex]:
name = classNames[matchIndex].upper()
#print(name)
y1,x2,y2,x1 = faceLoc
y1, x2, y2, x1 = y1*4,x2*4,y2*4,x1*4
cv2.rectangle(img,(x1,y1),(x2,y2),(0,255,0),2) #....., color, thikness
cv2.rectangle(img,(x1,y2-35),(x2,y2),(0,255,0),cv2.FILLED)
cv2.putText(img,name,(x1+6,y2-6),cv2.FONT_HERSHEY_COMPLEX,1,(255,255,255),2)
mark_attendance(name)
#self.Label_Show_Image=cv2.imshow('att',img)
#######################################
def update_frame(self):
ret, self.img = self.cap.read()
self.displayImage(self.img, self.encodeList, self.classNames, 1)
def displayImage(self, img, encodeList, classNames, window=1):
"""
:param img: frame from camera
:param encodeList: known face encoding list
:param classNames: known face names
:param window: number of window
:return:
"""
img = cv2.resize(img, (640, 480))
try:
img = self.face_rec_(img, encodeList, classNames)
except Exception as e:
print(e)
qformat = QImage.Format_Indexed8
if len(img.shape) == 3:
if img.shape[2] == 4:
qformat = QImage.Format_RGBA8888
else:
qformat = QImage.Format_RGB888
outImage = QImage(img, img.shape[1], img.shape[0], img.strides[0], qformat)
outImage = outImage.rgbSwapped()
if window == 1:
self.Label_Show_Image.setPixmap(QPixmap.fromImage(outImage))
self.Label_Show_Image.setScaledContents(True)
Hobby script kiddo here
I'm trying to make a bot that can beat humans at reaction quizes (such as this one). However, I think my code be more efficient and respond quicker.
The code I have below averages around 130 ms respond time.
import pandas as pd
import cv2
from PIL import Image, ImageGrab
import time
import pyautogui
import mouse
abc123=0
time.sleep(0)
while abc123==0:
im1 = ImageGrab.grab(bbox=(50, 150, 700, 400)) #x, y, w, h
img_np = np.array(im1)
frame = cv2.cvtColor(img_np, cv2.COLOR_BGR2RGB)
break
index=["color", "color_name", "hex", "R", "G", "B"]
csv = pd.read_csv(r'D:\code\colors1.csv', names=index, header=None)
clicked = False
r = g = b = xpos = ypos = 0
def recognize_color(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
def mouse_click(event, x, y, flags, param):
if True:
global b,g,r,xpos,ypos, clicked
clicked = True
xpos = x
ypos = y
b,g,r = frame[y,x]
b = int(b)
g = int(g)
r = int(r)
cv2.namedWindow('Color Recognition App')
cv2.setMouseCallback('Color Recognition App', mouse_click)
run_once = 0
pyautogui.click(x=200, y=150)
time.sleep(0)
while(1):
im1 = ImageGrab.grab(bbox=(50, 150, 700, 400)) #x, y, w, h
img_np = np.array(im1)
frame = cv2.cvtColor(img_np, cv2.COLOR_BGR2RGB)
mouse.move(1,1, absolute=False)
mouse.move(-1,-1, absolute=False)
cv2.imshow("Color Recognition App",frame)
if (clicked):
# print(g)
if g in range(200,250):
pyautogui.click(x=470, y=300)
clicked=False
#Break the loop when user hits 'esc' key
if cv2.waitKey(20) & 0xFF ==27:
break
cv2.destroyAllWindows()
csv = pd.read_csv(r'D:\code\colors1.csv', names=index, header=None)
requires this file -> https://file.io/mXCore9FqusW
Played around a little, made one that averages 60ms:
import PIL.ImageGrab
import mouse
while True:
rgb = PIL.ImageGrab.grab().load()[75,180]
rgb2=(78, 221, 113)
if rgb == rgb2:
mouse.click()
I'm tying to make a color detection system where when i click on a image it displays the color i just clicked on. I keep getting an error:
(TypeError: '<' not supported between instances of 'str' and 'int')
Here is the code I have written so far:
from tkinter import *
from tkinter import ttk
import cv2
import numpy as np
import webcolors
def click_event(event, x, y, flags, param):
if event == cv2.EVENT_LBUTTONDOWN:
blue = img[y, x, 0]
green = img[y, x, 1]
red = img[y, x, 2]
font = cv2.FONT_HERSHEY_SIMPLEX
colourcode = str(blue) + ", " + str(green) + ", " + str(red)
cv2.putText(img, colourcode, (x, y), font, .5, (0, 255, 255), 2)
cv2.imshow('image', img)
def closest_colour(requested_colour):
min_colours = {}
for key, name in webcolors.css3_hex_to_names.items():
r_c, g_c, b_c = webcolors.hex_to_rgb(key)
rd = (r_c - requested_colour[0]) ** 2
gd = (g_c - requested_colour[1]) ** 2
bd = (b_c - requested_colour[2]) ** 2
min_colours[(rd + gd + bd)] = name
return min_colours[min(min_colours.keys())]
def get_colour_name(requested_colour):
try:
closest_name = actual_name = webcolors.rgb_to_name(requested_colour)
except ValueError:
closest_name = closest_colour(requested_colour)
actual_name = None
return actual_name, closest_name
print(colourcode)
requested_colour = colourcode
actual_name, closest_name = get_colour_name(requested_colour)
print("Actual colour name:", actual_name, ", closest colour name:", closest_name)
img = cv2.imread('070929.jpg')
cv2.imshow('image', img)
cv2.resizeWindow('image', 250,500)
cv2.setMouseCallback('image', click_event)
cv2.waitKey(0)
cv2.destroyAllWindows()
You are passing strings inside:
colourcode = str(blue) + ", " + str(green) + ", " + str(red)
Consider rewriting your code to pass integers:
colourcode2 = (blue, green, red)
In my code after certain time (depend of the PC or OS) crashes. The error displayed is
libpng warning: Image width is zero in IHDR
libpng warning: Image height is zero in IHDR
libpng error: Invalid IHDR data
My code draw ROI on a video from webcam and take a snapshot. The ROI is deleted after 5-10 minutes (I'm not sure why, this is the error) and the picture saved not have dimensions then the error above is displayed but I'm not find the error. The instructions are, press "c" to stop the video and draw a ROI, press again "c" to take the picture, press "r" to resume the video, and repeat if you need another pictures.
I tested the code in Windows 10 and raspbian on a raspberry and the time is not the same but on both the program crashes. This is my code:
import cv2
# python PSI_Camera_test.py
class staticROI(object):
def __init__(self):
self.capture = cv2.VideoCapture(0)
self.capture.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
self.capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
# Bounding box reference points and boolean if we are extracting coordinates
self.image_coordinates = []
self.extract = False
self.selected_ROI = False
self.img_counter = 0
self.update()
def update(self):
while True:
if self.capture.isOpened():
# Read frame
(self.status, self.frame) = self.capture.read()
cv2.imshow('image', self.frame)
key = cv2.waitKey(2)
# Crop image
if key == ord('c'):
self.clone = self.frame.copy()
cv2.namedWindow('image')
cv2.setMouseCallback('image', self.extract_coordinates)
while True:
key = cv2.waitKey(2)
cv2.imshow('image', self.clone)
# Crop and display cropped image
if key == ord('c'):
self.crop_ROI()
img_name = "Images\opencv_frame_{}.png".format(
self.img_counter)
cv2.imwrite(img_name, self.cropped_image)
print("{} written!".format(img_name))
self.img_counter += 1
# Resume video
if key == ord('r'):
break
# Close program with keyboard 'esp'
if key % 256 == 27:
cv2.destroyAllWindows()
exit(1)
else:
pass
def extract_coordinates(self, event, x, y, flags, parameters):
# Record starting (x,y) coordinates on left mouse button click
if event == cv2.EVENT_LBUTTONDOWN:
self.image_coordinates = [(x, y)]
self.extract = True
# Record ending (x,y) coordintes on left mouse bottom release
elif event == cv2.EVENT_LBUTTONUP:
self.image_coordinates.append((x, y))
self.extract = False
self.selected_ROI = True
# Draw rectangle around ROI
cv2.rectangle(
self.clone, self.image_coordinates[0], self.image_coordinates[1], (0, 255, 0), 2)
# Clear drawing boxes on right mouse button click
elif event == cv2.EVENT_RBUTTONDOWN:
self.clone = self.frame.copy()
self.selected_ROI = False
def crop_ROI(self):
if self.selected_ROI:
self.cropped_image = self.frame.copy()
x1 = self.image_coordinates[0][0]
y1 = self.image_coordinates[0][1]
x2 = self.image_coordinates[1][0]
y2 = self.image_coordinates[1][1]
self.cropped_image = self.cropped_image[y1:y2, x1:x2]
print('Cropped image: {} {}'.format(
self.image_coordinates[0], self.image_coordinates[1]))
else:
print('Select ROI to crop before cropping')
# python PSI_Camera_test.py
if __name__ == '__main__':
static_ROI = staticROI()
Thanks in advance!
I'm using python-opencv to complete my undergraduate graduation project and I need to use MultiTracker to implement multi-target detection and tracking functions. However, I cannot cancel the target object after it disappeared from the screen. I'm not a student major in digital image processing, the problem bothers me a lot. Can anyone help me? The code is as follows:
import sys
import cv2
from random import randint
trackerTypes = ['BOOSTING', 'MIL', 'KCF', 'TLD', 'MEDIANFLOW', 'GOTURN', 'MOSSE', 'CSRT']
trackerType = trackerTypes[6] # KCF, MOSSE的效果还能接受,KCF效果最好,MOSSE速度最快
def adjust_frame(frame):
rows, cols, ch = frame.shape
M = cv2.getRotationMatrix2D((cols, rows), 1, 1) # 三个参数分别是旋转中心,旋转角度,比例
frame = cv2.warpAffine(frame, M, (cols, rows))
frame = frame[580:670, 470:1030]
frame = cv2.resize(frame, None, fx=1.5, fy=1.5, interpolation=cv2.INTER_CUBIC)
return frame
def createTrackerByName(trackerType):
# 通过跟踪器的名字创建跟踪器
if trackerType == trackerTypes[0]:
tracker = cv2.TrackerBoosting_create()
elif trackerType == trackerTypes[1]:
tracker = cv2.TrackerMIL_create()
elif trackerType == trackerTypes[2]:
tracker = cv2.TrackerKCF_create()
elif trackerType == trackerTypes[3]:
tracker = cv2.TrackerTLD_create()
elif trackerType == trackerTypes[4]:
tracker = cv2.TrackerMedianFlow_create()
elif trackerType == trackerTypes[5]:
tracker = cv2.TrackerGOTURN_create()
elif trackerType == trackerTypes[6]:
tracker = cv2.TrackerMOSSE_create()
elif trackerType == trackerTypes[7]:
tracker = cv2.TrackerCSRT_create()
else:
tracker = None
print('Incorrect tracker name')
print('Available tracker name')
for t in trackerTypes:
print(t)
return tracker
print('Default tracking algorithm is CSRT \n'
'Available tracking algorithms are:\n')
for t in trackerTypes:
print(t, end=' ')
videoPath = r'E:\python files\vehicle identification\4.MOV' # 设置加载的视频文件路径
cap = cv2.VideoCapture(videoPath) # 创建video capture 来读取视频文件
# 读取第一帧
ret, frame = cap.read()
frame = adjust_frame(frame)
# 如果无法读取视频文件就退出
if not ret:
print('Failed to read video')
sys.exit(1)
# 选择框
bboxes = []
colors = []
# OpenCV的selectROI函数不适用于在Python中选择多个对象
# 所以循环调用此函数,直到完成选择所有对象
while True:
# 在对象上绘制边界框selectROI的默认行为是从fromCenter设置为false时从中心开始绘制框,可以从左上角开始绘制框
bbox = cv2.selectROI('MultiTracker', frame) # 返回的四个值x, y, w, h
bboxes.append(bbox)
colors.append((randint(64, 255), randint(64, 255), randint(64, 255)))
print("Press q to quit selecting boxes and start tracking")
print("Press any other key to select next object")
k = cv2.waitKey(0)
if k == 113: # q is pressed
break
print('Selected bounding boxes {}'.format(bboxes))
# 初始化MultiTracker
# 有两种方法可以初始化multitracker
# 1. tracker = cv2.MultiTracker(“CSRT”)
# 所有跟踪器都添加到这个多路程序中
# 将使用CSRT算法作为默认值
# 2. tracker = cv2.MultiTracker()
# 未指定默认算法
# 使用跟踪算法初始化MultiTracker
# 指定跟踪器类型
# 创建多跟踪器对象
multiTracker = cv2.MultiTracker_create()
# 初始化多跟踪器
for bbox in bboxes:
multiTracker.add(createTrackerByName(trackerType), frame, bbox)
# 处理视频并跟踪对象
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
frame = adjust_frame(frame)
timer = cv2.getTickCount() # 计时点1
# 获取后续帧中对象的更新位置
ret, boxes = multiTracker.update(frame)
# 绘制跟踪的对象
for i, newbox in enumerate(boxes):
p1 = (int(newbox[0]), int(newbox[1])) # x, y坐标
p2 = (int(newbox[0] + newbox[2]), int(newbox[1] + newbox[3]))
cv2.rectangle(frame, p1, p2, colors[i], 2, 1)
fps = cv2.getTickFrequency() / (cv2.getTickCount() - timer) # 计时点2
cv2.putText(frame, "FPS : " + str(int(fps)), (10, 13), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (50, 170, 50), 2)
cv2.putText(frame, trackerType + " Tracker", (10, 28), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (50, 170, 50), 2)
cv2.imshow('MultiTracker', frame)
k = cv2.waitKey(1)
if k == 27:
break
elif k == ord('p'): # 按下p键可以新添加目标
bbox = cv2.selectROI('MultiTracker', frame) # 返回的四个值x, y, w, h
bboxes.append(bbox)
colors.append((randint(64, 255), randint(64, 255), randint(64, 255)))
multiTracker.add(createTrackerByName(trackerType), frame, bbox)