Python Opencv + Gdal

2

I am developing software to calculate NDVI. What is NDVI? is a mathematical calculation with which you can determine the level of vegetation stress NDVI = NIR-RED / NIR + RED This result varies from -1 to 1 I'm using OpenCV as a library for artificial vision and Gdal to help calculations.

My idea is to be able to "colorize" the ranges that NDVI delivers, for example for values < 0 color those pixels with a red color.

My problem is that I can not go through the data matrix.

I enclose the code:

# Importamos Librerias a utilizar
from osgeo import gdal
import cv2
import numpy as np

# Abrimos la imagen a utilizar
img = cv2.imread('image01.JPG')
# Pasamos de RGB a HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# Claros
lw_range = np.array([4, 150, 0])
# Oscuros
up_range = np.array([34, 255, 255])
#Crear una mascara con solo los pixeles dentro del rango de verdes
mask = cv2.inRange(hsv, lw_range, up_range)
# resta para mostrar imagen original
res = cv2.bitwise_and(img,img, mask= mask)
cv2.imwrite('imglimpia.tif',res)

# Procesamiento con Gdal
imgGedal = gdal.Open('imglimpia.tif', gdal.GA_ReadOnly)
num_bands = imgGedal.RasterCount
rows = imgGedal.RasterYSize
cols = imgGedal.RasterXSize
#print('Numero de Bandas {n}\n'.format(n=num_bands))

# Separamos por banda
blue  = imgGedal.GetRasterBand(3)
green = imgGedal.GetRasterBand(2)
red   = imgGedal.GetRasterBand(1)

blue_data  = blue.ReadAsArray()
green_data = green.ReadAsArray()
red_data   = red.ReadAsArray()
cv2.imwrite('azul.tif',blue_data)
cv2.imwrite('gren.tif',green_data)
cv2.imwrite('red.tif',red_data)

# Obtener Valores Minimo y Maximo
band_min, band_max, band_mean, band_stddev = blue.GetStatistics(0, 1)
print('Rango Azul: Minimo: {minimo} - Medio: {medio} - Maximo: {maximo} - Tamano: {sz}- STDDEV: {stddev}'
    .format(maximo=band_max,medio=blue_data.mean(),minimo=band_min,sz=blue_data.shape,stddev=band_stddev))


band_min, band_max, band_mean, band_stddev = green.GetStatistics(0, 1)
print('Rango Verde: Minimo: {minimo} - Medio: {medio} - Maximo: {maximo} - Tamano: {sz}- STDDEV: {stddev}'
    .format(maximo=band_max,medio=blue_data.mean(),minimo=band_min,sz=blue_data.shape,stddev=band_stddev))


band_min, band_max, band_mean, band_stddev = red.GetStatistics(0, 1)
print('Rango Rojo: Minimo: {minimo} - Medio: {medio} - Maximo: {maximo} - Tamano: {sz}- STDDEV: {stddev}'
    .format(maximo=band_max,medio=blue_data.mean(),minimo=band_min,sz=blue_data.shape,stddev=band_stddev))


# Calcular NDVI = ((Nir-Blue)/(Nir+Blue))
resta = cv2.subtract(red_data,blue_data)
suma = cv2.add(red_data,blue_data)
ndvi = cv2.divide(resta,suma)
print 'NDVI MIN   : ',ndvi.min()
print 'NDVI MEDIO : ',ndvi.mean()
print 'NDVI MAX   : ',ndvi.max()

After this, I want to go through the data array to color pixels

# Creamos los colores
greenyellow = [4,255,173]
yellow = [0,255,255]
yellowred = [4,111,255]
green = [0,255,0]
greenyellow = [0,255,146]
blue = [255,0,0]
red = [0,0,255]
white = [255,255,255]
black = [0,0,0]

y = np.zeros((4000,3000,3),np.uint8)  # img coloreada
cols,rows,band = y.shape
for i in range(rows):
        for j in range(cols):
            for k in ndvi[i,j]:
                print (str([i,j,k]) + '\n')
                if k < 0.0 :
                    y[i,j] = red
                    break
                if 0.0 < k < 0.2 :
                    y[i,j] = yellowred
                    break
                if 0.2 < k < 0.4 :
                    y[i,j] = yellow
                    break
                if 0.4 < k < 0.6 :
                    y[i,j] = greenyellow
                    break
                if k > 0.6 :
                    y[i,j] = green
                    break
                else:
                    y[i,j] = black
                    break
cv2.imwrite('NDVI.jpg',y)

this is the error that generates me:

for k in ndvi[j,i]:
TypeError: 'numpy.uint8' object is not iterable
    
asked by The_Chapu 01.08.2016 в 06:36
source

1 answer

1

The problem is that ndvi is a ndarray of 2 dimensions and when you assign values to both indexes it returns the item for that position of the ndarray and that is not iterable and is a scalar ( np.uint8 ) and, therefore, the for is 'broken' since it can not iterate over the scalar.

EDIT:

In addition, ndvi is an array with the form 3000 x 4000 and the one you are creating to fill, y , is 4000x3000 so you reach the limit in one of the dimensions.

I correct the code below:

Directly, in the loops you should do:

y = np.zeros((3000,4000,3),np.uint8)  # img coloreada
rows,cols,band = y.shape
for i in range(rows):
    for j in range(cols):
        k = ndvi[i,j] ## QUITAMOS EL BUCLE PARA 'k'
        print (str([i,j,k]) + '\n')
        if k < 0.0 :
            y[i,j] = red
            break
        if 0.0 < k < 0.2 :
            y[i,j] = yellowred
            break
        if 0.2 < k < 0.4 :
            y[i,j] = yellow
            break
        if 0.4 < k < 0.6 :
            y[i,j] = greenyellow
            break
        if k > 0.6 :
            y[i,j] = green
            break
        else:
            y[i,j] = black
            break

The final result I see is a black image so I think something of the algorithm must go wrong, but now, at least, the entire code is executed.

    
answered by 01.08.2016 в 08:15