Related
This is the condition.
if (car.y < 100): car.y = 100
if (car.y + car.height) > 500: car.y = 500 - car.height
I want to know how to write this using min and max.
This is what I tried.
car.y = max(100, min(500, car.y - car.height))
According to my knowledge, min(500, car.y - car.height) returns 500 if 500 < car.y - car.height, which means it cant ever be more than 500, capping the upper limit and since its in max(100, ...), the lower value cant be less than 100.
I used this test and everything works as expected. The values are capped between 100 and 500.
for i in range(100):
print(max(100, min(500, random.randint(10, 1000) - random.randint(10, 1000))))
Now here is where I am stuck.
In the following case.
y = 100
height = 10
while True:
if (y < 100): y = 100
if (y + height) > 500: y = 500 - height
y += 1
print(y)
It behaves as expected but in the following case:
y = 100
height = 10
while True:
y = max(100, min(500, y - height))
y += 1
print(y)
It just prints 101 continuously and doesn't increment at all. It's stuck at 101. Thank you for helping me.
Same as Blue_notes answer just the other way round.
car.y = max(car.y, 100);
car.y = min(car.y, 500-car.height)
or if you want it as one line
car.y = min(max(car.y, 100),500 - car.height)
If you try to run this code (I have used a for loop rather than a while to make it more testable):
y = 100
height = 10
for i in range(5):
h = min(500, y - height)
y = max(100, h)
print(h , ' ' , y , ' ', y+1, '\n')
y += 1
You will see that it gets stuck at 101. Why? Let's do the iteration together:
Loop 1
h is min between 500 and (100-10), thus it will be 90
y is max between 100 and 90, so it will be 100
y is plus 1, which now becomes 101
Loop 2
h is min between 500 and (101-10), so 91
y is max between 100 and 91, so? 100!
y is plus 1, so 100 + 1 now becomes 101... and this will continue forever, let's continue just to prove this:
Loop 3
h is min between 500 and (101-10), so 91
y is max between 100 and 91... 100!
y is plus 1, 101...
So as you can see, as the product of y will remain 101, no matter how many times we try, it will remain 101 in the end.
Now you know why it got stuck. Depending on what you need to do or what you are experimenting on, you can add another variable, allowing y to freely grow and make your code work as expected:
y = 100
height = 10
for i in range(25):
h = min(500, y - height)
z = max(100, h)
y += 1
print(h , ' ' , z , ' ', y, '\n')
And convert the for loop into a while as needed.
y = 100
height = 10
while True:
if (y < 100): y = 100
if (y + height) > 500: y = 500 - height
y += 1
print(y)
Snippet above makes it stuck at 491. Similar code in max min style is below:
y = 100
height = 10
while True:
y = min(500-height, max(100, y)) + 1
print(y)
The maximum that car.y can be is 500 - car.height (so you need to select the smaller of the two). The minimum that it can be is 100 (so you need to select the larger of this pair)
car.y = max(min(car.y, 500 - car.height), 100)
I use the CCL algorithm of Spencer Whitt from Github to remove detected road markings from Noise.
First, I run the CCL algorithm over an image so that it recognizes contiguous elements. Now I extended the algorithm so that it ignores elements with a small number of pixels. So I tried to sort and filter the dictionary created by the CCL algorithm. In the additional code, therefore, keys that are not enough are deleted with the corresponding values.
Unfortunately, the additional code not only deletes small elements, but also fragments up the "large" contiguous road markings. Why?
Image:
CCL algorithm:
from PIL import Image
import PIL
from PIL import ImageOps
import collections
import operator
import numpy as np
import sys
import math, random
from itertools import product
from ufarray import *
Image.MAX_IMAGE_PIXELS = 1000000000
import cv2
def run(img):
data = img.load()
width, height = img.size
# Union find data structure
uf = UFarray()
#
# First pass
#
# Dictionary of point:label pairs
labels = {}
for y, x in product(range(height), range(width)):
#
# Pixel names were chosen as shown:
#
# -------------
# | a | b | c |
# -------------
# | d | e | |
# -------------
# | | | |
# -------------
#
# The current pixel is e
# a, b, c, and d are its neighbors of interest
#
# 255 is white, 0 is black
# White pixels part of the background, so they are ignored
# If a pixel lies outside the bounds of the image, it default to white
#
# If the current pixel is white, it's obviously not a component...
if data[x, y] == 255:
pass
# If pixel b is in the image and black:
# a, d, and c are its neighbors, so they are all part of the same component
# Therefore, there is no reason to check their labels
# so simply assign b's label to e
elif y > 0 and data[x, y-1] == 0:
labels[x, y] = labels[(x, y-1)]
# If pixel c is in the image and black:
# b is its neighbor, but a and d are not
# Therefore, we must check a and d's labels
elif x+1 < width and y > 0 and data[x+1, y-1] == 0:
c = labels[(x+1, y-1)]
labels[x, y] = c
# If pixel a is in the image and black:
# Then a and c are connected through e
# Therefore, we must union their sets
if x > 0 and data[x-1, y-1] == 0:
a = labels[(x-1, y-1)]
uf.union(c, a)
# If pixel d is in the image and black:
# Then d and c are connected through e
# Therefore we must union their sets
elif x > 0 and data[x-1, y] == 0:
d = labels[(x-1, y)]
uf.union(c, d)
# If pixel a is in the image and black:
# We already know b and c are white
# d is a's neighbor, so they already have the same label
# So simply assign a's label to e
elif x > 0 and y > 0 and data[x-1, y-1] == 0:
labels[x, y] = labels[(x-1, y-1)]
# If pixel d is in the image and black
# We already know a, b, and c are white
# so simpy assign d's label to e
elif x > 0 and data[x-1, y] == 0:
labels[x, y] = labels[(x-1, y)]
# All the neighboring pixels are white,
# Therefore the current pixel is a new component
else:
labels[x, y] = uf.makeLabel()
#
# Second pass
#
uf.flatten()
colors = {}
# Image to display the components in a nice, colorful way
output_img = Image.new("RGB", (width, height))
outdata = output_img.load()
for (x, y) in labels:
# Name of the component the current point belongs to
component = uf.find(labels[(x, y)])
# Update the labels with correct information
labels[(x, y)] = component
# Associate a random color with this component
if component not in colors:
colors[component] = (random.randint(0,255), random.randint(0,255),random.randint(0,255))
# Colorize the image
outdata[x, y] = colors[component]
return (labels, output_img)
Additional code:
def main():
# Open the image
img = Image.open("files/motorway/gabor/motorway_gabor_S.tiff")
img = PIL.ImageOps.invert(img)
# Threshold the image, this implementation is designed to process b+w
# images only
img = img.point(lambda p: p > 190 and 255)
img = img.convert('1')
# labels is a dictionary of the connected component data in the form:
# (x_coordinate, y_coordinate) : component_id
#
# if you plan on processing the component data, this is probably what you
# will want to use
#
# output_image is just a frivolous way to visualize the components.
(labels, output_img) = run(img)
# output_img.show()
output_img.save("files/motorway/gabor/motorway_gabor_S_cc1.tiff")
################################################################################
sorted_x = sorted(labels.items(), key=operator.itemgetter(1))
str_labels = str(sorted_x) # Convert Dictionary to String, remove unnecessary characters
str_labels = str_labels.replace("{", "[")
str_labels = str_labels.replace("}", "]")
str_labels = str_labels.replace("(", "")
str_labels = str_labels.replace(")", "")
str_labels = str_labels.replace(":", ",")
# print str_labels[:100]
int_labels = eval(str_labels) # Transforming back into an integer list
i = 0
key = []
value = []
#int_labels2 = list(int_labels)
while i < len(int_labels)/3:
key.append(int_labels[3*i]) # x (keys)
key.append(int_labels[3 * i + 1]) # y (keys)
value.append(int_labels[3 * i + 2]) # values
i = i + 1
counter = collections.Counter(value) # Counting the frequency of "values"
counter_values = counter.values()
################################################################################
# Selection
# Sorting out "keys" and "values" that are too big/small
# key2 = relevant "keys"
# value2 = to key2 appropriate relevant values
i = 0
k = 0
v = 0
key2 = []
key3 = []
value2 = []
value3 = []
help = []
while i < len(counter_values):
if counter_values[i] >= 80:# and counter_values[i] <= 71:
value2.append(counter_values[v]*2)
v = v + 1
while k < counter_values[i]*2 + sum(help)*2:
key2.append(key[k])
k = k + 1
else:
value3.append(counter_values[v]*2)
v = v + 1
while k < counter_values[i]*2 + sum(help)*2:
key3.append(key[k])
k = k + 1
help.append(counter_values[i])
i = i + 1
#####################################################################
# Image to display the components in a nice, colorful way
width, height = img.size
output_img = Image.new("RGB", (width, height))
outdata = output_img.load()
# list (key2) to x- and y-tuple-pairs
i = 0
key2t = []
while i < len(key2):
key2t.append(tuple(key2[i:i + 2]))
i = i + 2
# transform value2-list
i = 0
j = 0
k = 0
value2_full = []
while i < len(value2):
while j < value2[i]:
value2_full.append(k)
j = j + 1
j = 0
i = i + 1
k = k + 1
d = dict(zip(key2t, value2_full))
colors = {}
i = 0
for (x, y) in d:
if value2_full[i] not in colors:
colors[value2_full[i]] = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
# Colorize the image
outdata[x, y] = colors[value2_full[i]]
output_img.save("files/motorway/gabor/motorway_gabor_S_cc2.tiff")
I am currently stumped by an artefact in my code. It appears to produce very sharp points in a grid pattern that have a noticeable difference in value to their neighbours.
I am following the blog post at http://www.bluh.org/code-the-diamond-square-algorithm/ and converting from whichever language they are using (assuming either C# or Java), and have double-checked that what I am doing should match.
Is there any chance that someone could have a browse over this, and see what I'm doing wrong? I've stepped through it at smaller levels, and stopped it on specific iterations of the algorithm (by unrolling the top loop, and explicitly calling the algorithm a set number of times) and everything seems to work until we get to the very last set of points/pixels.
I use a class (called Matrix) to access the list, and wrap any out of bounds values.
The code for the algorithm is as follows:
class World :
def genWorld (self, numcells, cellsize, seed):
random.seed(seed)
self.dims = numcells*cellsize
self.seed = seed
self.cells = Matrix(self.dims, self.dims)
# set the cells at cellsize intervals
half = cellsize/2
for y in range(0, self.dims, cellsize):
for x in range(0, self.dims, cellsize):
self.cells[x,y] = random.random()
scale = 1.0
samplesize = cellsize
while samplesize > 1:
self._diamondSquare(samplesize, scale)
scale *= 0.8
samplesize = int(samplesize/2)
# I need to sort out the problem with the diamond-square algo that causes it to make the weird gridding pattern
def _sampleSquare(self, x, y, size, value):
half = size/2
a = self.cells[x-half, y-half]
b = self.cells[x+half, y-half]
c = self.cells[x-half, y+half]
d = self.cells[x+half, y+half]
res = min(((a+b+c+d+value)/5.0), 1.0)
self.cells[x, y] = res
def _sampleDiamond(self, x, y, size, value):
half = size/2
a = self.cells[x+half, y]
b = self.cells[x-half, y]
c = self.cells[x, y+half]
d = self.cells[x, y-half]
res = min(((a+b+c+d+value)/5.0), 1.0)
self.cells[x, y] = res
def _diamondSquare(self, stepsize, scale):
half = int(stepsize/2)
for y in range(half, self.dims+half, stepsize):
for x in range(half, self.dims+half, stepsize):
self._sampleSquare(x, y, stepsize, random.random()*scale)
for y in range(0, self.dims, stepsize):
for x in range(0, self.dims, stepsize):
self._sampleDiamond(x+half, y, stepsize, random.random()*scale)
self._sampleDiamond(x, y+half, stepsize, random.random()*scale)
and is called with:
w = World()
w.genWorld(16, 16, 1) # a 256x256 square world, since the numcells is multiplied by the cellsize to give us the length of ONE side of the resulting grid
then I save to file to check the result:
file = io.open("sample.raw",'wb')
arr = [int(i * 255) for i in w.cells.cells] # w.cells.cells should not have a value >= 1.0, so what's going on?
ind = 0
for a in arr:
if a > 255:
print ("arr["+str(ind)+"] ::= "+str(a))
ind += 1
file.write(bytearray(arr))
file.close()
which gives the result:
EDIT: Okay, so it appears that I managed to get it working. I swapped from using functions for working out the diamond and square steps to doing it all in the _diamondSquare() function, but this wasn't the only thing. I also found out that random.random() provides values in the range [0.0 ->1.0), when I was expecting values in the range [-1.0 -> 1.0). After I corrected this, everything started working properly, which was a relief.
Thanks for the advice everyone, here's the working code in case anyone else is struggling with something similar:
Random Function
# since random.random() gives a value in the range [0.0 -> 1.0), I need to change it to [-1.0 -> 1.0)
def rand():
mag = random.random()
sign = random.random()
if sign >=0.5:
return mag
return mag * -1.0
Matrix class
class Matrix:
def __init__(self, width, height):
self.cells = [0 for i in range(width*height)]
self.width = width
self.height = height
self.max_elems = width*height
def _getsingleindex(self, ind):
if ind < 0:
ind *= -1
while ind >= self.max_elems:
ind -= self.max_elems
return ind
def _getmultiindex(self, xind, yind):
if xind < 0:
xind *= -1
if yind < 0:
yind *= -1
while xind >= self.width:
xind -= self.width
while yind >= self.height:
yind -= self.height
return xind + (yind*self.height)
def __getitem__(self, inds):
# test that index is an integer, or two integers, and throw an indexException if not
if hasattr(inds, "__len__"):
if len(inds) > 1:
return self.cells[self._getmultiindex(int(inds[0]), int(inds[1]))]
return self.cells[self._getsingleindex(int(inds))]
def __setitem__(self, inds, object):
# test that index is an integer, or two integers, and throw an indexException if not
if hasattr(inds, "__len__"):
if len(inds) > 1:
self.cells[self._getmultiindex(int(inds[0]),int(inds[1]))] = object
return self.cells[self._getmultiindex(int(inds[0]),int(inds[1]))]
self.cells[self._getsingleindex(int(inds))] = object
return self.cells[self._getsingleindex(int(inds))]
def __len__(self):
return len(self.cells)
The Actual Diamond-Square Generation
# performs the actual 2D generation
class World:
def genWorld (self, numcells, cellsize, seed, scale = 1.0):
random.seed(seed)
self.dims = numcells*cellsize
self.seed = seed
self.cells = Matrix(self.dims, self.dims)
mountains = Matrix(self.dims, self.dims)
# set the cells at cellsize intervals
for y in range(0, self.dims, cellsize):
for x in range(0, self.dims, cellsize):
# this is the default, sets the heights randomly
self.cells[x,y] = random.random()
while cellsize > 1:
self._diamondSquare(cellsize, scale)
scale *= 0.5
cellsize = int(cellsize/2)
for i in range(len(mountains)):
self.cells[i] = self.cells[i]*0.4 + (mountains[i]*mountains[i])*0.6
def _diamondSquare(self, stepsize, scale):
half = int(stepsize/2)
# diamond part
for y in range(half, self.dims+half, stepsize):
for x in range(half, self.dims+half, stepsize):
self.cells[x, y] = ((self.cells[x-half, y-half] + self.cells[x+half, y-half] + self.cells[x-half, y+half] + self.cells[x+half, y+half])/4.0) + (rand()*scale)
# square part
for y in range(0, self.dims, stepsize):
for x in range(0, self.dims, stepsize):
self.cells[x+half,y] = ((self.cells[x+half+half, y] + self.cells[x+half-half, y] + self.cells[x+half, y+half] + self.cells[x+half, y-half])/4.0)+(rand()*scale)
self.cells[x,y+half] = ((self.cells[x+half, y+half] + self.cells[x-half, y+half] + self.cells[x, y+half+half] + self.cells[x, y+half-half])/4.0)+(rand()*scale)
Main Function (added for completeness)
# a simple main function that uses World to create a 2D array of diamond-square values, then writes it to a file
def main():
w = World()
w.genWorld(20, 16, 1)
mi = min(w.cells.cells)
ma = max(w.cells.cells) - mi
# save the resulting matrix to an image file
file = io.open("sample.raw",'wb')
maxed = [(i-mi)/ma for i in w.cells.cells]
arr = [int(i * 255) for i in maxed]
file.write(bytearray(arr))
file.close()
I'm using four inputs for my function: a picture object, x coordinate, y coordinate, and the height/width of the square. I want to separately average all the red, green, and blue values of the picture. I'm having trouble with the accumulator variables of the RGB pixels and checking the bounds of the square. Can anyone help me out?
from imageTools import *
p1 = makePicture("flower.jpg")
def averageColor(pic, xCord, yCord, width):
rAcc = 0
gAcc = 0
bAcc = 0
for x in range(xCord, xCord + width):
for y in range(yCord, yCord + width):
picWidth = getWidth(pic)
picHeight = getHeight(pic)
if x <= picWidth and y <= picHeight:
pixel = getPixel(pic, xCord, yCord)
r = getRed(pixel)
g = getGreen(pixel)
b = getBlue(pixel)
rAcc = rAcc + 1
gAcc = gAcc + 1
bAcc = bAcc + 1
avgRed = r / rAcc
avgGreen = g / gAcc
avgBlue = b / bAcc
newColor = makeColor(avgRed, avgGreen, avgBlue)
return newColor
col1 = averageColor(p1, 0, 150, 100)
print(col1)
You want to use < and not <= when comparing indexes because indexes are zero based. For instance if the picture is 10 pixels wide 9 is the index to the last pixel
Also you are overwriting your accumulation variables r, g and b. You need to do
r = r + getRed(...)
oh. Also it looks like you are trying to use xCoord and yCoord to get the pixel rather than your x and y variables
i wrote this little code to compare the pixels greyscale values of two 100x100 jpeg images.
However, the performance is very disappointing (1.5 Seconds for 10.000 comparisons). Is there a way to achieve a better performance?
Here is the code:
import cv2
import numpy as np
import math
import datetime
img1 = cv2.imread('Testbild 2014-08-23 17:27:25.141362.jpeg', cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread('Testbild 2014-08-23 17:27:25.061802.jpeg', cv2.IMREAD_GRAYSCALE)
height, width =img1.shape
cnt = 0
threshold = 10
print("start:" + str(datetime.datetime.now()))
for y in range(0 , height):
for x in range(0 , width):
val1 = img1.item(y,x)
val2 = img2.item(y,x)
diff_abs = math.fabs(int(val1)-int(val2))
if diff_abs > threshold:
cnt += 1
if x == height and y == width:
break
if x == height:
x=0
if y == width:
y=0
print("end:" + str(datetime.datetime.now()))
print("Result: " + str(cnt))
Many thanks for your answers!
The double loop:
for y in range(0 , height):
for x in range(0 , width):
val1 = img1.item(y,x)
val2 = img2.item(y,x)
diff_abs = math.fabs(int(val1)-int(val2))
if diff_abs > threshold:
cnt += 1
if x == height and y == width:
break
if x == height:
x=0
if y == width:
y=0
can be replaced by:
diff_abs = np.abs(img1-img2)
cnt = (diff_abs > threshold).sum()
This takes advantage of NumPy array's ability to do fast element-wise arithmetic.
The condition
x == height and y == width
is never true. If height < width, then y will never equal width (since y is in range(0, height)). If height > width, then x will never equal height. and if height == width, then neither x nor y will ever equal height.
The condition
if x == height:
x=0
does nothing useful, since even if x == height, the assignment to x is lost on the next iteration of the loop.
The same goes for
if y == width:
y=0