Remove list in lists that satisfied the condition - python

I'm trying to make a quick OCR for specific use, I know should've just write a preprocessor for normal OCR and that would been faster but this idea came up to me first and I figure I should just try it anyway haha. This program would take a picture on a region of screen and identify the number within it, as of right now, it's only 0 and 1 but I've been working on it and stuck with some problems. Here is my code
while True:
if keyboard.is_pressed('`'):
Firstlist = list(pyautogui.locateAllOnScreen(image[0], confidence = 0.95,region=( 1570 , 990 , 230 , 70 )))
print(len(Firstlist))
Firstlist1 = list(pyautogui.locateAllOnScreen(image1, confidence = 0.95,region=( 1570 , 990 , 230 , 70 ))) + Firstlist
print(len(Firstlist1))
print(Firstlist)
if len(Firstlist) > 0:
print(Firstlist[0][0])
#compare all first instance of that number and eliminate all duplicated with in a different of 5 x pixel
break
Which would identify some predetermined set of number like this on screen and right now, it would give me a set of coordinate for number zero on screen, here is the result, please ignore other parts, it's just me playing around. Problem with this is pyautogui.locateAllOnScreen would sometimes generate duplicate value of the same picture within the coordinate ranging from approx 0-5 pixels if not set the confidence level right.
Example:
Value supposed to be [ (1655,1024,20,26),(1675,1024,20,26) ] but will yield a third value like [ (1655,1024,20,26), (1658,1024,20,26), (1675,1024,20,26) ].
And that's why I'm trying to make a correction for this. Is there anyway to identified if that x value of second duplicate coordinate is within a range of 0-5 pixels to the first coordinate and just delete it, moving the rest up the ladder so that the number would come up right and in order? Thank you!
Note: I'm still working on learning the list removal process by myself, and read the removing list with lambda to me is like gibberish. Please forgive me if something is wrong. Have a good day y'all!

You can try this.
if len(Firstlist) > 2:
elems = [f[0] for f in Firstlist] # create a list of just first index
i = 0
while i < len(elems) - 1: # iterate through the list with i
j = i + 1
while j < len(elems): # iterate through the rest of the list with j
if abs(elems[i] - elems[j]) <= 5: # if item at index i is within 5 pixels of item at index j
del elems[j] # delete item j and continue
else:
j += 1 # otherwise move to next item
i += 1 # Move to next i item

list1 = [ (1655,1024,20,26), (1658,1024,20,26), (1675,1024,20,26) ]
x = [list1[0]] + [x for x in list1 if abs(list1[0][0] - x[0]) > 5]
print(x)
Output:
[(1655, 1024, 20, 26), (1675, 1024, 20, 26)]

Related

Recursive python function to make two arrays equal?

I'm attempting to write python code to solve a transportation problem using the Least Cost method. I have a 2D numpy array that I am iterating through to find the minimum, perform calculations with that minimum, and then replace it with a 0 so that the loops stops when values matches constantarray, an array of the same shape containing only 0s. The values array contains distances from points in supply to points in demand. I'm currently using a while loop to do so, but the loop isn't running because values.all() != constantarray.all() evaluates to False.
I also need the process to repeat once the arrays have been edited to move onto the next lowest number in values.
constarray = np.zeros((len(supply),len(demand)) #create array of 0s
sandmoved = np.zeros((len(supply),len(demand)) #used to store information needed for later
totalcost = 0
while values.all() != constantarray.all(): #iterate until `values` only contains 0s
m = np.argmin(values,axis = 0)[0] #find coordinates of minimum value
n = np.argmin(values,axis = 1)[0]
if supply[m] > abs(demand[m]): #all demand numbers are negative
supply[m]+=demand[n] #subtract demand from supply
totalcost +=abs(demand[n])*values[m,n]
sandmoved[m,n] = demand[n] #add amount of 'sand' moved to an empty array
values[m,0:-1] = 0 #replace entire m row with 0s since demand has been filled
demand[n]=0 #replace demand value with 0
elif supply[m]< abs(demand[n]):
demand[n]+=supply[m] #combine positive supply with negative demand
sandmoved[m,n]=supply[m]
totalcost +=supply[m]*values[m,n]
values[:-1,n]=0 #replace entire column with 0s since supply has been depleted
supply[m] = 0
There is an additional if statement for when supply[m]==demand[n] but I feel that isn't necessary. I've already tried using nested for loops, and so many different syntax combinations for a while loop but I just can't get it to work the way I want it to. Even when running the code block over over by itself, m and n stay the same and the function removes one value from values but doesn't add it to sandmoved. Any ideas are greatly appreciated!!
Well, here is an example from an old implementation of mine:
import numpy as np
values = np.array([[3, 1, 7, 4],
[2, 6, 5, 9],
[8, 3, 3, 2]])
demand = np.array([250, 350, 400, 200])
supply = np.array([300, 400, 500])
totCost = 0
MAX_VAL = 2 * np.max(values) # choose MAX_VAL higher than all values
while np.any(values.ravel() < MAX_VAL):
# find row and col indices of min
m, n = np.unravel_index(np.argmin(values), values.shape)
if supply[m] < demand[n]:
totCost += supply[m] * values[m,n]
demand[n] -= supply[m]
values[m,:] = MAX_VAL # set all row to MAX_VAL
else:
totCost += demand[n] * values[m,n]
supply[m] -= demand[n]
values[:,n] = MAX_VAL # set all col to MAX_VAL
Solution:
print(totCost)
# 2850
Basically, start by choosing a MAX_VAL higher than all given values and a totCost = 0. Then follow the standard steps of the algorithm. Find row and column indices of the smallest cell, say m, n. Select the m-th supply or the n-th demand whichever is smaller, then add what you selected multiplied by values[m,n] to the totCost, and set all entries of the selected row or column to MAX_VAL to avoid it in the next iterations. Update the greater value by subtracting the selected one and repeat until all values are equal to MAX_VAL.

Code is executing process that should have been denied in the initial statement and i dont know why

so i have a data set that contains data similar to: (Left:date, Middle: value, Right:time difference between dates).
I am developing a code that will scan this data set and if the first value in the right column is bigger than 1 and the successive ones are less than 1, then get me the max value(middle) and tell me the date it happened and put those in a new list. So in the above example, it should check the first 5 rows, find the max value to be 13.15 and tell me the date it happened and store it in a new list. However, my code is not doing this, in fact sometimes is actually produces duplicates and im having trouble finding out why. Code is below:
list_final_multiple = []
for i in range(0,len(file_dates_list)): #gets all of the rest of the data
n = 1
if (file_gap_list[i] > 1 or i == 0) and file_gap_list[i+n] <= 1:
while ((i + n) < len(file_dates_list)) and (file_gap_list[i + n] <= 1):
n = n + 1
max_value = (max(file_hs_list[i:i + n]))
max_value_location = file_hs_list.index(max_value)
list_final_multiple.append([file_dates_list[max_value_location], file_hs_list[max_value_location]])
any help would be appreciated.

Create "synthetic points"

I need to create inside a python routine, something that I am calling "synthetic points".
I have a series of data which vary between -1 and 1, however, when I put this data on a chart, they form a trapezoidal chart.
What I would like to do is create points where the same x-axis value, could take two y-axis values, and then, this will create a chart with
straight lines making a "rectangular chart"
An example the format data that I have:
0;-1
1;-1
2;-1
3;-1
4;-1
5;-1
6;-1
7;1
8;1
9;1
10;1
11;1
12;1
13;1
14;1
15;1
16;-1
17;-1
18;-1
19;-1
20;-1
For example, in this case, I would need the data assume the following format:
0;-1
1;-1
2;-1
3;-1
4;-1
5;-1
6;-1
6;1 (point 6 with two values)
7;1
8;1
9;1
10;1
11;1
12;1
13;1
14;1
15;1
15;-1 (point 15 with two values)
16;-1
17;-1
18;-1
19;-1
20;-1
So what you need to do is, always when I had a value change, this will create a new point. This makes the graph, rectangular, as the only possible values for the y variable are -1 and 1.
The code I need to enter is below. What was done next was just to put the input data in this format of -1 and 1.
arq = open('vazdif.out', 'rt')
list = []
i = 0
for row in arq:
field = row.split(';')
vaz = float(field[2])
if vaz < 0:
list.append("-1")
elif vaz > 0:
list.append("1")
n = len(list)
fou = open('res_id.out','wt')
for i in range(n):
fou.write('{};{}\n'.format(i,list[i]))
fou.close
Thank you for your help
P.s. English is not my first language, forgive my mistakes on write or on the code.
I added a new value prev_value, if the previous value is of the opposite sign (multiply with the current value < 0), it adds an extra index to the list.
I think the field[1] and field[2] are probably wrong, but I'll trust your code works so far. Similar with fou, I would replace with with open ...
arq = open('vazdif.out', 'rt')
list = []
i = 0
prev_value = 0
for row in arq:
field = row.split(';')
xxx = int(field[1])
vaz = float(field[2])
if vaz * prev_value < 0:
list.append([list[-1][0], - list[-1][1]])
if vaz < 0:
list.append([xxx, -1])
else:
list.append([xxx, 1])
prev_val = vaz
fou = open('res_id.out','wt')
for i in list:
fou.write(f'{i[0]};{i[1]}\n')
fou.close

Grouping images by time interval python

I have a script with taking out exif data from images, and putting it into to the list, I sort my list after and that's what i have its a list of lists, on first position its a image time in seconds and 2nd place its a image path, its my list,
[[32372, 'F:\rubish\VOL1\cam\G0013025.JPG'], [32373, 'F:\rubish\VOL1\cam\G0013026.JPG'], [32373, 'F:\rubish\VOL1\cam\G0013027.JPG'],.... etc etc etc
That a script with grouping my images made by #blhsing , with works great, but I want to start my grouping , not from first image , start grouping by given position
That a script:
groups = []
for r in img:
if groups and r[0] - groups[-1][-1][0] <= 5:
groups[-1].append(r)
else:
groups.append([r])
for g in groups:
print(g[0][1], g[0][0], g[-1][0], g[-1][1])
And that what I have and , its does not work well , its taking only one image, , does no create a group , did somebody can help me please to fix it ??
groups = []
print(iii, "iii")
#print(min_list, " my min list ")
img.sort()
cnt = 0
mili = [32372, 34880]
for n in min_list:
#print(n, "mili")
for i in img:
#print(i[0])
if n == i[0]:
if groups and i[0] - groups[-1][-1][0] <= 5:
groups[-1].append(i)
else:
groups.append([i])
for ii in groups:
print(ii[0][1], ii[0][0], ii[-1][0], ii[-1][1])
Over here I have my min_list with 2 position means I want to create only 2 groups , and classifier only images starting from those 2 position , with interval as before 5 seconds.
Since your img list is sorted by time already, you can iterate through the records and append them to the last sub-list of the output list (named groups in my example code) if the time difference to the last entry is no more than 5 seconds; otherwise put the record into a new sub-list of the output list. Keep in mind that in Python a subscript of -1 means the last item in a list.
groups = []
for r in img:
if groups and r[0] - groups[-1][-1][0] <= 5:
groups[-1].append(r)
else:
groups.append([r])
for g in groups:
print(g[0][1], g[0][0], g[-1][0], g[-1][1])
Sure! I just actually wrote this same algorithm the other day, but for JavaScript. Easy to port to Python...
import pprint
def group_seq(data, predicate):
groups = []
current_group = None
for datum in data:
if current_group:
if not predicate(current_group[-1], datum): # Abandon the group
current_group = None
if not current_group: # Need to start a new group
current_group = []
groups.append(current_group)
current_group.append(datum)
return groups
data = [
[32372, r'F:\rubish\VOL1\cam\G0013025.JPG'],
[32373, r'F:\rubish\VOL1\cam\G0013026.JPG'],
[32373, r'F:\rubish\VOL1\cam\G0013027.JPG'],
[32380, r'F:\rubish\VOL1\cam\G0064646.JPG'],
[32381, r'F:\rubish\VOL1\cam\G0064646.JPG'],
]
groups = group_seq(
data=data,
predicate=lambda a, b: abs(a[0] - b[0]) > 5,
)
pprint.pprint(groups)
outputs
[[[32372, 'F:\\rubish\\VOL1\\cam\\G0013025.JPG'],
[32373, 'F:\\rubish\\VOL1\\cam\\G0013026.JPG'],
[32373, 'F:\\rubish\\VOL1\\cam\\G0013027.JPG']],
[[32380, 'F:\\rubish\\VOL1\\cam\\G0064646.JPG'],
[32381, 'F:\\rubish\\VOL1\\cam\\G0064646.JPG']]]
Basically the predicate is a function that should return True if b belongs in the same group as a; for your use case, we look at the (absolute) difference of the first items in the tuples/lists, which is the timestamp.

Referencing a conditional random element of an array and replacing it

This is my second question post on StackOverflow relating to coding in Python/Numpy.
I feel like there is definitely some sort of function which does the pseudocode:
np.random.choice([a[i-1,j],a[i+1,j],a[i,j-1],a[i,j+1]])==0 = 9
Essentially, I would like the random function to select a cell adjacent to mine (up, down, left, right) with the value 0, and replace said cell with a 9
Unforunately, I know why the code I typed is illegal. The first half of the statement returns a True/False boolean as I have used a comparison/checking operator. I can't set this into a value 9.
If I split the code-load into two codes and used an if statement with the random.choice (looking at an adjacent element that equalled zero), then following this, I would need some sort of function or definition to recall which cell (up down left or right) did the random generator originally select, to which I can then set it to 9.
Kind Regards,
EDIT: I may as well attach a sample code, so you can simply just run this (I am including my error)
a = np.empty((6,6,))
a[:] = 0
a[2,3]=a[3,3]=a[2,4] = 1
for (i,j), value in np.ndenumerate(a):
if a[i,j]==1:
np.random.choice([a[i-1,j],a[i+1,j],a[i,j-1],a[i,j+1]])==0 = 9
You could select from a range of directions (up, down, left, right) that map to specific coordinate movements in the 2D array, like this:
# generate a dataset
a = np.zeros((6,6))
a[2,3]=a[3,3]=a[2,4] = 1
# map directions to coordinate movements
nesw_map = {'left': [-1, 0], 'top': [0, 1], 'right': [1,0], 'bottom': [0,-1]}
directions = nesw_map.keys()
# select only those places where a == 1
for col_ind, row_ind in zip(*np.where(a == 1)): # more efficient than iterating over the entire array
x = np.random.choice(directions)
elm_coords = col_ind + nesw_map[x][0], row_ind + nesw_map[x][1]
if a[elm_coords] == 0:
a[elm_coords] = 9
Note that this does not do any type of bounds checking (so if a 1 appears at the edge, you might select an item "off the grid" which will result in an error).
This is the most "basic" way of getting what you need (Adding a try/except statement provides error checking, so you can prevent any unwanted errors):
import random,numpy
a = numpy.empty((6,6,))
a[:] = 0
a[2,3]=a[3,3]=a[5,5] = 1
for (i,j), value in numpy.ndenumerate(a):
var = 0
if a[i,j]==1:
while var==0:
x=random.randrange(0,4) #Generate a random number
try:
if x==0 and a[i-1,j]==0:
a[i-1,j] =9 #Do this if x = 0
elif x==1 and a[i+1,j]==0:
a[i+1,j] =9 #Do this if x = 1
elif x==2 and a[i,j-1]==0:
a[i,j-1] =9 #Do this if x = 2
elif x==3 and a[i,j+1]==0:
a[i,j+1] =9 #Do this if x = 3
var=1
except:
var=0
print a

Categories