HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Distinct nearest pixels for floating-point coordinates

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
distinctcoordinatespointnearestfloatingpixelsfor

Problem

dem_rows and dem_cols contain float values for a number of things i can identify in an image, but I need to get the nearest pixel for each of them, and than to make sure I only get the unique points, and no duplicates.

The problem is that this code is ugly and as far as I get it, as unpythonic as it gets. If there would be a pure-numpy-solution (without for-loops) that would be even better.

# next part is to make sure that we get the rounding done correctly, and than to get the integer part out of it 
# without the annoying floatingpoint-error, and without duplicates
fielddic={}
for i in range(len(dem_rows)):
    # here comes the ugly part: abusing the fact that i overwrite dictionary keys if I get duplicates
    fielddic[int(round(dem_rows[i]) + 0.1), int(round(dem_cols[i]) + 0.1)] = None
# also very ugly: to make two arrays of integers out of the first and second part of the keys 
field_rows = numpy.zeros((len(fielddic.keys())), int)
field_cols = numpy.zeros((len(fielddic.keys())), int)
for i, (r, c) in enumerate(fielddic.keys()):
    field_rows[i] = r
    field_cols[i] = c

Solution

I'm not sure what you are doing, exactly, but looping over range(len(...)) is never very pythonic. Since you only use the index to look up values, you should just take the pairs using zip.

Also, that round() + 0.1 thing is unnecessary. Floats represent all integers in their accurate area exactly. If you are outside the accurate area (i.e. an exponent larger than the number of mantissa bits), that addition will not change the value of the float either. Thus, you can simply cast the result of round() to an integer.

If you need to take the unique items of something, the best way is to not use a dict, but a set.

int_rows = map(lambda x: int(round(x)), dem_rows)
int_cols = map(lambda x: int(round(x)), dem_cols)
s = set(zip(int_rows, int_cols))


Then iterate over the set, or unzip it into two sequences for constructing the arrays.

Note: In python 2.x map and zip create lists, so you may want to use itertools.izip and imap. In python 3.x they are fine as is.

Code Snippets

int_rows = map(lambda x: int(round(x)), dem_rows)
int_cols = map(lambda x: int(round(x)), dem_cols)
s = set(zip(int_rows, int_cols))

Context

StackExchange Code Review Q#33562, answer score: 3

Revisions (0)

No revisions yet.