# Extract selected pixel values with their coordinates

My goal is to get the coordinates of all pixels with a specified value (ex: maximum and minimum pixel values).

``````# imports
import numpy as np
import pandas as pd
import geopandas as gpd
import rasterio

src = rasterio.open('./data/thhz.tif')

# get maximum and minimal values
max = np.max(band)
min = np.min(band)

# convert raster into shapefile
# got this from https://gis.stackexchange.com/questions/346288/extract-all-pixels-values-from-geotiff-with-python
### this process is too slow from here need to use other methods
px_vals = []

for x in range(band.shape[0]):
for y in range(band.shape[1]):
px_vals.append({'x': x,
'y': y,
'value': band[x, y]})

# convert list to dataframe
vals = pd.DataFrame(data=px_vals, columns=['x', 'y', 'value'])

# convert dataframe to geopandas
vals['geometry'] = gpd.points_from_xy(vals['x'], vals['y'])
vals = gpd.GeoDataFrame(vals, geometry='geometry', crs='EPSG:4326')

# transform coordinates with affine of raster
# get affine matrix with src.profile
vals['geometry'] = vals.affine_transform([0.001, 0.0, 2.616837667, 0.0, -0.001, 11.815923996])
# this also was not well converted

# slice values with coordinates
min_pixels = vals[vals['value'] == max]
max_pixels = vals[vals['value'] == min]

``````

Looping over a numpy array will always be slower than using vectorized numpy operations only. Try:

``````min_rows, min_cols = np.where(band == np.min(band))
max_rows, max_cols = np.where(band == np.max(band))
``````

`band == np.min(band)` gives back a boolean array, broadcasted to be in the same shape as `band`, and containing `True` where the element is equal to the min value.

`np.where()` gives back indices where the condition is true, if you only specify the first argument.

• Is it possible to get the coordinates instead of #row & #cols?
– pyaj
Mar 26 at 0:22
• min_lons, min_lats = transform.xy(thhz.transform, min_rows, min_cols)
– pyaj
Mar 26 at 11:39
• max_lons, max_lats = transform.xy(thhz.transform, max_rows, max_cols)
– pyaj
Mar 26 at 11:40
• from rasterio import transform
– pyaj
Mar 26 at 11:40
– pyaj
Mar 26 at 11:41

I just worked out a solution

``````def coordinates_and_values(raster, pixel_values):
"""
this function extracts longitude and latitudes of list of raster pixel values
pixel_values: list of pixel values
exception: pixel value must be found more than one time in raster else len of float error
"""
df = pd.DataFrame()                         # create dataframe
for i in pixel_values:                      # iterate between list of pixel values
rows, cols = np.where(raster_band == i) # extract row and column numbers for each pixel
rows, cols = transform.xy(raster.transform, rows, cols) # transform row and column numbers to coordinates
values = np.array([i] * len(rows))      # create array containing n pixel value of n coordinates
df_i = pd.DataFrame(zip(rows, cols, values), columns=['lon','lat', 'pixel']) # create dataframe for one pixel value
df = df.append(df_i)                    # append to get dataframe of lon and lat of list of pixel values
return df
``````

Example:

``````coordinates_and_values(src, [-7, -6, -5, 6])
``````