jueves, 8 de febrero de 2018

Introducción de objetos tipo polígono (círculos, cuadrados, rectángulos) y texto en imágenes con OpenCV

En este artículo se adaptó un código para incrementar el contraste de una imagen RGB y mejorar su nitidez. Se tiene en mente como objetivo la posibilidad de identificar objetos de una misma clase y contarlos (tales como plantas de cultivo).

Sin embargo, el proceso no es trivial. Los clasificadores de cascada de Haar proporcionados por OpenCV (es decir, los detectores de Viola-Jones), para el reconocimiento de objetos, si bien son extremadamente rápidos requieren mucho tiempo de entrenamiento y producen detecciones falsas positivas.

Por tanto, en este post sólo se va a probar la colocación de diferentes objetos de tipo polígono (círculos, cuadrados, rectángulos) y texto que corresponden al resultado de los diferentes algoritmos una vez que han "identificado" la consulta. El código probado se encuentra a continuación:

  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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
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")

sharpen = np.array((
    [-1, -1, -1],
    [-1,  9, -1],
    [-1, -1, -1]), dtype="int")  #pag. 56 book
    
emboss = np.array((
    [-2, -1, 0],
    [-1, 1, 1],
    [ 0, 1, 2]), dtype="int")

#sharpen = np.array((
#    [-2, -2, -2],
#    [-2,  17, -2],
#    [-2, -2, -2]), dtype="int") 

#sharpen = np.array((
#    [-3, -3, -3],
#    [-3,  25, -3],
#    [-3, -3, -3]), 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),
    #("emboss", emboss),
    #("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/palma.tif")
image = cv2.imread("/home/zeito/Desktop/convolutions-opencv/utah_lake.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.namedWindow('original2', cv2.WINDOW_NORMAL)
    cv2.rectangle(image,(500,30),(680,330),(0,255,0),2)
    cv2.circle(image,(300,100), 63, (0,0,255), 2)
    cv2.circle(image,(300,300), 63, (255,255,0), -1)
    cv2.ellipse(image,(750,256),(50,100),0,0,360,(255,0,255),2)
    pts = np.array([[10,5],[20,400],[100,200],[50,10]], np.int32)
    cv2.polylines(image,[pts],True,(0,255,255),2)
    """'FONT_HERSHEY_COMPLEX', 'FONT_HERSHEY_COMPLEX_SMALL', 'FONT_HERSHEY_DUPLEX', 'FONT_HERSHEY_PLAIN', 
    'FONT_HERSHEY_SCRIPT_COMPLEX', 'FONT_HERSHEY_SCRIPT_SIMPLEX', 'FONT_HERSHEY_SIMPLEX', 
    'FONT_HERSHEY_TRIPLEX', 'FONT_ITALIC'"""
    font = cv2.FONT_HERSHEY_TRIPLEX
    cv2.putText(image,'utah_lake.tif',(40,440), font, 3,(255,255,255),2)
    cv2.imshow("original2", image)
    #cv2.imshow("{} - convole".format(kernelName), convoleOutput)
    #cv2.namedWindow('emboss - opencv1', cv2.WINDOW_NORMAL)
    cv2.imshow("{} - opencv1".format(kernelName), opencvOutput)
#    cv2.imshow("{} - opencv2".format(kernelName), opencvOutput2)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

Después de ejecutado en la Python Console de QGIS se obtiene lo siguiente:


Es de hacer notar que OpenCV trabaja con índices de fila, columna por lo que en el caso de los SIGs se hace necesario la transformación de coordenadas x, y a estos valores.

No hay comentarios: