El post anterior incluye una referencia de la cual adapté el procedimiento para obtener los subarrays a los cuales allí se hacía mención y cuya temática principal era el tratamiento de imágenes.
El artículo referencia tenía como objetivo entender el significado y la aplicación de la convolución de imágenes para difuminarlas, incrementar su contraste o delimitar bordes a través de la aplicación de diferentes filtros que allí se denominaban kernels empleando OpenCV con Python.Por otra parte, viendo el enorme potencial del módulo me dispuse a modificar ligeramente el script allí contenido para ver como se comportaba con el tratamiento de imágenes GeoTiff georreferenciadas. Como sospechaba que de alguna manera se perdería la referencia espacial de la imagen (o desconozco, por ahora, la manera de obtenerla e incorporarla con este módulo) pensé que el usó simultáneo con GDAL podía ser útil para estas tareas.
El código completo adaptado se incluye a continuación. Sólo considero el realce por contraste (sharpen) y usé una imagen tif con los tres canales RGB.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | from skimage.exposure import rescale_intensity import numpy as np import argparse import cv2 def convolve(image, kernel): # grab the spatial dimensions of the image, along with # the spatial dimensions of the kernel (iH, iW) = image.shape[:2] (kH, kW) = kernel.shape[:2] # allocate memory for the output image, taking care to # "pad" the borders of the input image so the spatial # size (i.e., width and height) are not reduced pad = (kW - 1) / 2 image = cv2.copyMakeBorder(image, pad, pad, pad, pad, cv2.BORDER_REPLICATE) output = np.zeros((iH, iW), dtype="float32") # loop over the input image, "sliding" the kernel across # each (x, y)-coordinate from left-to-right and top to # bottom for y in np.arange(pad, iH + pad): for x in np.arange(pad, iW + pad): # extract the ROI of the image by extracting the # *center* region of the current (x, y)-coordinates # dimensions roi = image[y - pad:y + pad + 1, x - pad:x + pad + 1] # perform the actual convolution by taking the # element-wise multiplicate between the ROI and # the kernel, then summing the matrix k = (roi * kernel).sum() # store the convolved value in the output (x,y)- # coordinate of the output image output[y - pad, x - pad] = k # rescale the output image to be in the range [0, 255] output = rescale_intensity(output, in_range=(0, 255)) output = (output * 255).astype("uint8") # return the output image return output # construct average blurring kernels used to smooth an image smallBlur = np.ones((7, 7), dtype="float") * (1.0 / (7 * 7)) largeBlur = np.ones((21, 21), dtype="float") * (1.0 / (21 * 21)) # construct a sharpening filter sharpen = np.array(( [0, -1, 0], [-1, 5, -1], [0, -1, 0]), dtype="int") # construct the Laplacian kernel used to detect edge-like # regions of an image laplacian = np.array(( [0, 1, 0], [1, -4, 1], [0, 1, 0]), dtype="int") # construct the Sobel x-axis kernel sobelX = np.array(( [-1, 0, 1], [-2, 0, 2], [-1, 0, 1]), dtype="int") # construct the Sobel y-axis kernel sobelY = np.array(( [-1, -2, -1], [0, 0, 0], [1, 2, 1]), dtype="int") # construct the kernel bank, a list of kernels we're going # to apply using both our custom `convole` function and # OpenCV's `filter2D` function kernelBank = ( #("small_blur", smallBlur), #("large_blur", largeBlur), ("sharpen", sharpen), #("laplacian", laplacian), #("sobel_x", sobelX), #("sobel_y", sobelY) ) # load the input image and convert it to grayscale image = cv2.imread("/home/zeito/Desktop/convolutions-opencv/utah_lake.tif") #image = cv2.imread("/home/zeito/Desktop/convolutions-opencv/palma.tif") gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # loop over the kernels for (kernelName, kernel) in kernelBank: # apply the kernel to the grayscale image using both # our custom `convole` function and OpenCV's `filter2D` # function print("[INFO] applying {} kernel".format(kernelName)) convoleOutput = convolve(gray, kernel) opencvOutput = cv2.filter2D(gray, -1, kernel) #ddepth=-1, the output image will have the same depth as the source. opencvOutput2 = cv2.filter2D(image, -1, kernel) #ddepth=-1, the output image will have the same depth as the source. # show the output images #cv2.imshow("original1", gray) cv2.imshow("original2", image) #cv2.imshow("{} - convole".format(kernelName), convoleOutput) #cv2.imshow("{} - opencv1".format(kernelName), opencvOutput) cv2.imshow("{} - opencv2".format(kernelName), opencvOutput2) cv2.waitKey(0) cv2.destroyAllWindows() |
La aplicación del código anterior a la referida imagen produce una considerable nitidez de la misma. No obstante, al grabarla con el método 'imwrite' se pierde la georreferenciación (aunque ésto se puede remediar fácilmente con gdalinfo y gdal_translate en Python).
Otra imagen (esta vez con una resolución submétrica) donde probé el filtro sharpen fue en la de un cultivo de palma aceitera donde interesaba individualizar las plantas para contarlas y estimar la densidad del cultivo.
Como puede observarse, el incremento de la nitidez es apreciable en la imagen inferior y las plantas de palma son claramente identificables visualmente del bosque aledaño. Ahora sólo resta como aplicar los algoritmos para la segregación e identificación de objetos previo al proceso de contaje.
No hay comentarios:
Publicar un comentario