I am trying to extract all the information of the game bubbleshooter from my browser window. It works when I try to extract it on the normal chrome browser but when I try to use selenium and chromedriver it doesn't work anymore. Let me be more specific, I am trying to extract the current and next ball from the game window,
As you can see it detects the blue ball, but when I run the same environment in chromedriver It doesn't
Is there something I'm missing about chromedrivers ? I am using chrome version 109.0.5414.75 and so is my chromedriver
Some extra information
driver = webdriver.Chrome()
driver.get("https://www.bubbleshooter.net")
this is how I use the chromedriver, I use OpenCV to analyze the image and pyautogui to take the screenshot. I'm not sure if the code is relevant here but If someone asks I can upload it
Thank you in advance for any help you can offer me
the code:
def extract_current_next_ball(self,image):
colour_dictionary = {
1: [253,239,1], # cyan
2: [180,10,171], # purple
3: [1,228,227], # yellow
4: [33,241,1], # green
5: [213,17,1], # blue
6: [0,7,227] # red
}
x_locations = []
for key, val in colour_dictionary.items():
colour = np.array(val)
lower_colour = colour - 15
upper_colour = lower_colour + 15
lower_colour[lower_colour < 0] = 0
upper_colour[upper_colour > 255] = 255
components = cv.inRange(image,lower_colour,upper_colour)
# cv.imshow('components',components)
# cv.waitKey()
(num_labels, _labels, stats, _centroids) = cv.connectedComponentsWithStats(components, 4) # step 4
for i in range(num_labels):
x = stats[i, cv.CC_STAT_LEFT]
if (x > 0):
x_locations.append((x, key))
if (len(x_locations) == 0):
return [1,1]
max_x = max(x_locations,key=lambda x: x[0])
min_x = min(x_locations,key=lambda x: x[0])
current_colour = max_x[1]
next_colour = min_x[1]
return [current_colour,next_colour]
With this code I loop over all the different colours and try to find anything that matches that range, I then store the leftmost coordinate of the found component, and for the next ball I use the minimum value, and for the current ball the maximum value
Related
I am editing this block of code and I want to make it so that if the value of "timeDiff" goes below .5 and 1 it will change the output color to red or yellow respectively. I am new to python so I know this is a very simple question, but I am not sure of how to color it the way I want it to.
# CALCULATE TIME DIFERENCES
dPosition = sorted(drivers, key=lambda x: x.position)
if LeaderboardRow.update_type == INFO_TYPE.GAPS:
for i in range(1, len(dPosition)):
driver_ahead, driver = dPosition[i-1], dPosition[i]
timeDiff = driver.split_times[driver.current_split - 1] - driver_ahead.split_times[driver.current_split - 1]
if timeDiff < 0: continue # ignore these times, happens on overtakes
if driver.position > totalDrivers: continue # might try to update before it is possible
driver.timeDiff = timeDiff
if timeDiff < 1:
timeDiff color = style.RED #-----#
if timeDiff > 60:
leaderboard[driver.position].update_time("+1 MIN")
else:
leaderboard[driver.position].update_time("+" + time_to_string(timeDiff*1000))
leaderboard[0].update_time("Interval") # Force it
elif LeaderboardRow.update_type == INFO_TYPE.POSITIONS:
for d in dPosition:
posDiff = d.starting_position - d.position - 1
leaderboard[d.position].update_positions(posDiff)
I left out other parts of the code to not make it any longer, but I left #-----# where I was looking for help.
I've trying to implement transition from an amount of space to another which is similar to acceleration and deceleration, except i failed and the only thing that i got from this was this infinite stack of mess, here is a screenshot showing this in action:
you can see a very black circle here, which are in reality something like 100 or 200 circles stacked on top of each other
and i reached this result using this piece of code:
def Place_circles(curve, circle_space, cs, draw=True, screen=None):
curve_acceleration = []
if type(curve) == tuple:
curve_acceleration = curve[1][0]
curve_intensity = curve[1][1]
curve = curve[0]
#print(curve_intensity)
#print(curve_acceleration)
Circle_list = []
idx = [0,0]
for c in reversed(range(0,len(curve))):
for p in reversed(range(0,len(curve[c]))):
user_dist = circle_space[curve_intensity[c]] + curve_acceleration[c] * p
dist = math.sqrt(math.pow(curve[c][p][0] - curve[idx[0]][idx[1]][0],2)+math.pow(curve [c][p][1] - curve[idx[0]][idx[1]][1],2))
if dist > user_dist:
idx = [c,p]
Circle_list.append(circles.circles(round(curve[c][p][0]), round(curve[c][p][1]), cs, draw, screen))
This place circles depending on the intensity (a number between 0 and 2, random) of the current curve, which equal to an amount of space (let's say between 20 and 30 here, 20 being index 0, 30 being index 2 and a number between these 2 being index 1).
This create the stack you see above and isn't what i want, i also came to the conclusion that i cannot use acceleration since the amount of time to move between 2 points depend on the amount of circles i need to click on, knowing that there are multiple circles between each points, but not being able to determine how many lead to me being unable to the the classic acceleration formula.
So I'm running out of options here and ideas on how to transition from an amount of space to another.
any idea?
PS: i scrapped the idea above and switched back to my master branch but the code for this is still available in the branch i created here https://github.com/Mrcubix/Osu-StreamGenerator/tree/acceleration .
So now I'm back with my normal code that don't possess acceleration or deceleration.
TL:DR i can't use acceleration since i don't know the amount of circles that are going to be placed between the 2 points and make the time of travel vary (i need for exemple to click circles at 180 bpm of one circle every 0.333s) so I'm looking for another way to generate gradually changing space.
First, i took my function that was generating the intensity for each curves in [0 ; 2]
Then i scrapped the acceleration formula as it's unusable.
Now i'm using a basic algorithm to determine the maximum amount of circles i can place on a curve.
Now the way my script work is the following:
i first generate a stream (multiple circles that need to be clicked at high bpm)
this way i obtain the length of each curves (or segments) of the polyline.
i generate an intensity for each curve using the following function:
def generate_intensity(Circle_list: list = None, circle_space: int = None, Args: list = None):
curve_intensity = []
if not Args or Args[0] == "NewProfile":
prompt = True
while prompt:
max_duration_intensity = input("Choose the maximum amount of curve the change in intensity will occur for: ")
if max_duration_intensity.isdigit():
max_duration_intensity = int(max_duration_intensity)
prompt = False
prompt = True
while prompt:
intensity_change_odds = input("Choose the odds of occurence for changes in intensity (1-100): ")
if intensity_change_odds.isdigit():
intensity_change_odds = int(intensity_change_odds)
if 0 < intensity_change_odds <= 100:
prompt = False
prompt = True
while prompt:
min_intensity = input("Choose the lowest amount of spacing a circle will have: ")
if min_intensity.isdigit():
min_intensity = float(min_intensity)
if min_intensity < circle_space:
prompt = False
prompt = True
while prompt:
max_intensity = input("Choose the highest amount of spacing a circle will have: ")
if max_intensity.isdigit():
max_intensity = float(max_intensity)
if max_intensity > circle_space:
prompt = False
prompt = True
if Args:
if Args[0] == "NewProfile":
return [max_duration_intensity, intensity_change_odds, min_intensity, max_intensity]
elif Args[0] == "GenMap":
max_duration_intensity = Args[1]
intensity_change_odds = Args[2]
min_intensity = Args[3]
max_intensity = Args[4]
circle_space = ([min_intensity, circle_space, max_intensity] if not Args else [Args[0][3],circle_space,Args[0][4]])
count = 0
for idx, i in enumerate(Circle_list):
if idx == len(Circle_list) - 1:
if random.randint(0,100) < intensity_change_odds:
if random.randint(0,100) > 50:
curve_intensity.append(2)
else:
curve_intensity.append(0)
else:
curve_intensity.append(1)
if random.randint(0,100) < intensity_change_odds:
if random.randint(0,100) > 50:
curve_intensity.append(2)
count += 1
else:
curve_intensity.append(0)
count += 1
else:
if curve_intensity:
if curve_intensity[-1] == 2 and not count+1 > max_duration_intensity:
curve_intensity.append(2)
count += 1
continue
elif curve_intensity[-1] == 0 and not count+1 > max_duration_intensity:
curve_intensity.append(0)
count += 1
continue
elif count+1 > 2:
curve_intensity.append(1)
count = 0
continue
else:
curve_intensity.append(1)
else:
curve_intensity.append(1)
curve_intensity.reverse()
if curve_intensity.count(curve_intensity[0]) == len(curve_intensity):
print("Intensity didn't change")
return circle_space[1]
print("\n")
return [circle_space, curve_intensity]
with this, i obtain 2 list, one with the spacing i specified, and the second one is the list of randomly generated intensity.
from there i call another function taking into argument the polyline, the previously specified spacings and the generated intensity:
def acceleration_algorithm(polyline, circle_space, curve_intensity):
new_circle_spacing = []
for idx in range(len(polyline)): #repeat 4 times
spacing = []
Length = 0
best_spacing = 0
for p_idx in range(len(polyline[idx])-1): #repeat 1000 times / p_idx in [0 ; 1000]
# Create multiple list containing spacing going from circle_space[curve_intensity[idx-1]] to circle_space[curve_intensity[idx]]
spacing.append(np.linspace(circle_space[curve_intensity[idx]],circle_space[curve_intensity[idx+1]], p_idx).tolist())
# Sum distance to find length of curve
Length += abs(math.sqrt((polyline[idx][p_idx+1][0] - polyline[idx][p_idx][0]) ** 2 + (polyline [idx][p_idx+1][1] - polyline[idx][p_idx][1]) ** 2))
for s in range(len(spacing)): # probably has 1000 list in 1 list
length_left = Length # Make sure to reset length for each iteration
for dist in spacing[s]: # substract the specified int in spacing[s]
length_left -= dist
if length_left > 0:
best_spacing = s
else: # Since length < 0, use previous working index (best_spacing), could also jsut do `s-1`
if spacing[best_spacing] == []:
new_circle_spacing.append([circle_space[1]])
continue
new_circle_spacing.append(spacing[best_spacing])
break
return new_circle_spacing
with this, i obtain a list with the space between each circles that are going to be placed,
from there, i can Call Place_circles() again, and obtain the new stream:
def Place_circles(polyline, circle_space, cs, DoDrawCircle=True, surface=None):
Circle_list = []
curve = []
next_circle_space = None
dist = 0
for c in reversed(range(0, len(polyline))):
curve = []
if type(circle_space) == list:
iter_circle_space = iter(circle_space[c])
next_circle_space = next(iter_circle_space, circle_space[c][-1])
for p in reversed(range(len(polyline[c])-1)):
dist += math.sqrt((polyline[c][p+1][0] - polyline[c][p][0]) ** 2 + (polyline [c][p+1][1] - polyline[c][p][1]) ** 2)
if dist > (circle_space if type(circle_space) == int else next_circle_space):
dist = 0
curve.append(circles.circles(round(polyline[c][p][0]), round(polyline[c][p][1]), cs, DoDrawCircle, surface))
if type(circle_space) == list:
next_circle_space = next(iter_circle_space, circle_space[c][-1])
Circle_list.append(curve)
return Circle_list
the result is a stream with varying space between circles (so accelerating or decelerating), the only issue left to be fixed is pygame not updating the screen with the new set of circle after i call Place_circles(), but that's an issue i'm either going to try to fix myself or ask in another post
the final code for this feature can be found on my repo : https://github.com/Mrcubix/Osu-StreamGenerator/tree/Acceleration_v02
I'm making a smart bicycle backlight with Raspberry Pi and a SenseHat on top of it.
I'm measuring the output values of the SenseHat's accelerometer. There are actually three values reported as x, y, z and what I'm trying to know is whether my bicycle has been stationary for let's say 15 seconds or more. So if these values have been staying the same for over 15 seconds I'll turn off the backlight. And then if they start changing and stay like that for over 15 seconds, I want it to engage and start functioning again.
So far I've implemented strobe effect that auto activates when the bicycle is in idle. A steering detection - I show arrow animations to left and right based on the object detection sensor i put near the handlebar. I also implemented a brake detection. Once the accelerometer detects the braking, i show full red light.
If you check the code, you can see it's a bit tricky since the whole thing is in while loop and I need to make this detection as an if condition and then add else below, put rest of my existing if conditions there (such as deacceleration or turning detection)
So how do I make Python measure certain values for 15 seconds without using time.delay and do things based on whether they change or stay the same?
while True:
ser.flushInput()
ser.flushOutput()
x, y, z = sense.get_accelerometer_raw().values()
x = round(x, 2)
y = round(y, 2)
z = round(z, 2)
print("x=%s, y=%s, z=%s" % (x, y, z))
input = ser.read() #serial input i'm getting from arduino, it tells me if my left or right steering sensors are triggerred.
yon = input.decode("utf-8")
int(yon)
if (z > 0.20): #If deacceleration is detected
fren() # brake function is called
else: # if no breaking is detected...
if (yon == "1"): #if left turn sensor triggered
sag_ok() #show left turn animation on led matrix
elif (yon =="2"): # if right turn sensor triggered
sol_ok() #show right turn animation on led matrix
else: #anything else
strobe() #show strobe effect if nothing else is detected
There's a number of smaller things that need to be addressed first:
input = ser.read(). input is actually a builtin and shouldn't be used as a variable name
int(yon) does nothing. You may well convert it to an int but the result is lost because you don't assign the result back to a name
if (z > 0.20) and all your other if checks - the brackets actually do nothing here; you can drop them.
A bigger thing to address: That loop is going full-pelt on the CPU core for absolutely no reason. Thousands of times a second, constantly. You should introduce a time.sleep to reduce the load.
Given that, you can achieve your desired output with a mixture of a Boolean flag and a record of when the accelerometer last gave 0 values.
import time
import datetime as dt
last_zeros = None
countdown_started = False
while True:
ser.flushInput()
ser.flushOutput()
x, y, z = sense.get_accelerometer_raw().values()
x = round(x, 2)
y = round(y, 2)
z = round(z, 2)
print("x=%s, y=%s, z=%s" % (x, y, z))
if x == 0 and y == 0 and z == 0:
if countdown_started:
duration = (dt.datetime.utcnow() - last_zeros_time).total_seconds()
if duration > 15:
# Do something to turn the light off here
continue
else:
countdown_started = True
last_zeros_time = dt.datetime.utcnow()
else:
countdown_started = False
sensor_input = ser.read()
yon = sensor_input.decode("utf-8")
if (z > 0.20):
fren()
else:
if (yon == "1"):
sag_ok()
elif (yon =="2"):
sol_ok()
else:
strobe()
time.sleep(0.5)
The basic idea is to keep track of the last time when motion (or non-motion) was detected. If it was more than 15 seconds ago, then turn off (on) the light.
Something like this:
from time import monotonic
TAIL_LIGHT_DELAY = 15
time_of_last_motion = monotinic()
time_of_last_stop = monotonic()
while True:
now = monotonic()
motion = (abs(x) > 0.2) or (abs(y) > 0.2) or (abs(z) > 0.2)
if motion:
time_of_last_motion = now
if now - time_of_last_stop > TAIL_LIGHT_DELAY:
turn_on_tail_light()
else:
time_of_last_stop = now
if now - time_of_last_motion > TAIL_LIGHT_DELAY:
turn_off_tail_light()
Hi I was wondering if this was possible at all, since I tried it but my variable was always empty. In my project, I'm tracking a static object and a laser pointer via a PiCamera on my raspberry pi, and I calculate the centroids of their contours as (smallx,smally) and (small2x,small2y) respectively.
I use the difference between their coordinates to see if the pointer should go up, down, left, or right in order to meet the 1st static object. After that, it'll choose a direction betweeen 1 through 4 to move, because my direction controls aren't perfectly on an x-y axis and are slanted.
I left the controls and the contour finding out from here and shortened my total code just so that you wouldn't be met with a giant pile of slop to sort through.
EDIT: I' don't think with my understanding I could provide something runnable without posting a couple hundred lines and my little device, but I'll boil it down and post the exact portion of my code where this is relevant. Running Python 2.7.3, using opencv2.4.10
Code:
#import libraries like picamera and opencv
#set empty variables like:
up = down = left = right = set()
smallx = smally = small2x = small2y = 0
#etc etc
with picamera.PiCamera() as camera:
with picamera.array.PiRGBArray(camera) as rawCapture:
#Calibrate my controls with the camera. updates the up, down, left, and right sets.
with picamera.PiCamera() as camera:
with picamera.array.PiRGBArray(camera) as rawCapture:
# Take pictures, threshold them, find contours, append their arrays to list
if len(cnts)>0: #If any objects were identified
contm = sorted(smalList, key=lambda tup: tup[1])
smallest = cnts[smalList[0][0]] #**Take smallest object(my static object)**
smallM = cv2.moments(smallest)
smallx = int(smallM['m10']/smallM['m00']) #**Calculate xcoord**
smally = int(smallM['m01']/smallM['m00']) #**Calculate ycoord**
cv2.line(frame, (smallx,smally), (smallx,smally), 1, 8,0) #Draws centroid
# print(len(cnts))
if len(cnts)==2: #If only 2 objects were identified
smallester = cnts[smalList[1][0]] #** Take pointer object **
small2 = cv2.moments(smallester)
small2x = int(small2['m10']/small2['m00']) #**Calculate xcoord**
small2y = int(small2['m01']/small2['m00']) #**Calculate ycoord**
x = small2x - smallx
y = small2y - smally
print x #These prints return a value
print y
if x < 0: #Difference = Pointer - Object
s1 = right
if x >0:
s1 = left
if y < 0:
s2 = down
if y >0:
s2 = up
print s1, s2 #set([]),set([])
print up,down,left,right #set([1,2]),set([3,4]),set([1,4]),set([2,3])
selecty = s1&s2 #set([])
#Tell the pointer where to go
Should I even be using sets?
Use s1 = s2 = set() instead of = 0.
As for your second question, there are probably better and more known ways to go around your problem. For example, using bit logic:
right = 1
up = 2
left = 4
down = 8
select = 0
if (small2x - smallx) < 0:
select |= right
if (small2x - smallx) >0:
select |= left
if (small2y - smally) < 0:
select |= down
if (small2y - smally) >0:
select |= up
print(select)
print("You chose %s%s%s%s" %("UP " if select & up else "",
"DOWN " if select & down else "",
"LEFT " if select & left else "",
"RIGHT" if select & right else ""))
#Do things after
So i've got an image in input an i transformed it into an array. There is two ball, and i want to remove one ball.
My idea is to run through a loop, and detect line by line if there is a red pixel. And if in this array at an i, and there is not red pixel in i+1 it erase the entire rest of the line.
for i in range(0, len(data)):
h = h + 1
#print("0"),
if (i>1) and (((data[i - 1])[1] > 40 and (data[i - 1])[2] > 40 ) and ((data[i + 1])[1] > 40 and (data[i+1])[2])):
print("_"),
elif (data[i])[1] < 40 and (data[i])[2] < 40 and (data[i])[0] > 50 :
j = j + 1
print "#" ,
else :
print("."),
#else :
# print data[i],
if h == 64 :
h = 0
test = True
print("\n")
What is wrong with my code and how can i erase a ball through my method ?
If you just want to delete anything on the left side:
data[:,:data.shape[1]/2] = 0
or right side:
data[:,data.shape[1]/2:] = 0
If your problem is that you have balls (red, green and blue) in an array (numpy) and there's no background or noise. For simplicity, if the color of red = 1, green = 2 and blue = 3 then:
data[np.where(data == 1)] = 0
will remove the red ball. For more sophisticated detection-needs you can use below...
You can use label from scipy.ndimage given that your data is an np-array by simply saying (of course if your balls get too overlapped they may not be separated):
from scipy.ndimage import label
labled_data, labels = label(data)
#If you want to remove the first ball
labled_data[np.where(labled_data == 1)] = 0
#Then your second ball will be where the labled data is 2
#Else if you just temporary want to know where the second ball is:
labled_data == 2
#Will be true for those places