首页 > 解决方案 > create a grid on 2D array and count values

问题描述

Hy everyone,

I'm working with astronomical fits image. From the fits file, I had this 2D image / 2D numpy array.

enter image description here

My goal is first to create a grid (as I drew manually above, for example), than, from every cell of that grid, counting the values inside it. The size of the box must be fixed at 25x25 pixel.

I'm confused about what is the best way to do that. I was wondering if there is a way using pyregion or maybe geopandas (which I am less familiar with). Any suggestion or examples are welcome!

With pyregion I am able to draw a specific, let's say, sqared region, and then calculate the counts inside it one at a time... but what would be perfect is to do all at once and than create a map of the count in each cell.

标签: pythonarraysimagegrid

解决方案


如果你有numpy.array那么你可以cv2.rectangle用来绘制网格。

img_grid = cv2.rectangle(img_grid, (x, y, BOX_W+1, BOX_H+1), GREEN)

您可以在for-loop 中执行此操作。

for y in range(0, height, BOX_H):
    for x in range(0, width, BOX_W):
        img_grid = cv2.rectangle(img_grid, (x, y, BOX_W+1, BOX_H+1), GREEN)

cv2也用来加载图像和保存图像。

import cv2

GREEN = (0, 255, 0)  # BGR instead of RGB
BOX_W = 25
BOX_H = 25

img = cv2.imread('lenna.png')
height, width = img.shape[:2]

img_grid = img.copy()  # to keep original image for calculations

for y in range(0, height, BOX_H):
    for x in range(0, width, BOX_W):
        img_grid = cv2.rectangle(img_grid, (x, y, BOX_W+1, BOX_H+1), GREEN)

cv2.imshow('image', img_grid)
cv2.waitKey(0)

cv2.imwrite('lenna_grid.png', img_grid)

cv2.destroyAllWindows()

来自维基百科的图像Lenna

在此处输入图像描述


与使用for-loop 获取框中的值并进行计算的方式相同。

for y in range(0, height, BOX_H):
    for x in range(0, width, BOX_W):
        x1 = x
        y1 = y
        x2 = x + BOX_W
        y2 = y + BOX_H

        data = img[y1:y2, x1:x2]

        result = data.mean()

        print(f'mean for [{y1:3}:{y2:3}, {x1:3}:{x2:3}]: {result:6.2f}')

结果:

mean for [  0: 25,   0: 25]: 155.60
mean for [  0: 25,  25: 50]: 159.80
mean for [  0: 25,  50: 75]: 125.37
mean for [  0: 25,  75:100]: 110.78
mean for [  0: 25, 100:125]: 121.00
mean for [  0: 25, 125:150]: 132.41
mean for [  0: 25, 150:175]: 134.54
mean for [  0: 25, 175:200]: 135.22
mean for [  0: 25, 200:225]: 134.36
mean for [  0: 25, 225:250]: 134.32
mean for [  0: 25, 250:275]: 133.63
mean for [  0: 25, 275:300]: 131.61

完整代码:

import cv2

GREEN = (0, 255, 0)  # BGR instead of RGB
BOX_W = 25
BOX_H = 25

img = cv2.imread('lenna.png')   # `img` is a `numpy array` (but in BGR instead of RGB)
height, width = img.shape[:2]

img_grid = img.copy()  # to keep original image for calculations

for y in range(0, height, BOX_H):
    for x in range(0, width, BOX_W):
        img_grid = cv2.rectangle(img_grid, (x, y, BOX_W+1, BOX_H+1), GREEN)

cv2.imshow('image', img_grid)
cv2.waitKey(0)  # press any key to close window

cv2.imwrite('lenna_grid.png', img_grid)

cv2.destroyAllWindows()

# -----------------------------------------

for y in range(0, height, BOX_H):
    for x in range(0, width, BOX_W):
        x1 = x
        y1 = y
        x2 = x + BOX_W
        y2 = y + BOX_H
        data = img[y1:y2, x1:x2]
        result = data.mean()
        print(f'mean for [{y1:3}:{y2:3}, {x1:3}:{x2:3}]: {result:6.2f}')

编辑:

您也可以在没有的情况下绘制矩形cv2.rectangle- 您可以替换数组中的像素

    # left line   
    img_grid[y1:y2, x1] = GREEN

    # right line
    img_grid[y1:y2, x2] = GREEN

    # top line
    img_grid[y1, x1:x2] = GREEN

    # bottom line
    img_grid[y2, x1:x2] = GREEN

但它可能需要检查是否x2并且y2仍在图像内。

    if x2 >= width:
        x2 = width-1
    if y2 >= height:
        y2 = height-1

#import numpy as np
import cv2

GREEN = (0, 255, 0)  # BGR instead of RGB
BOX_W = 25
BOX_H = 25

img = cv2.imread('lenna.png')
height, width = img.shape[:2]

img_grid = img.copy()  # to keep original image for calculations

for y in range(0, width, BOX_H):
    for x in range(0, height, BOX_W):

        x1 = x
        y1 = y
        x2 = x + BOX_W
        y2 = y + BOX_H
        
        if x2 >= width:
            x2 = width-1
        if y2 >= height:
            y2 = height-1
            
        # left line   
        img_grid[y1:y2, x1] = GREEN
        
        # right line
        img_grid[y1:y2, x2] = GREEN
        
        # top line
        img_grid[y1, x1:x2] = GREEN
        
        # bottom line
        img_grid[y2, x1:x2] = GREEN

cv2.imshow('image', img_grid)
cv2.waitKey(0)

cv2.imwrite('lenna_grid.png', img_grid)

cv2.destroyAllWindows()

BTW: cv2也可以使用窗口来选择一些区域(ROI)

您绘制矩形并按SPACE接受。在最后一个矩形按下ESC后使用区域。

#import numpy as np
import cv2

GREEN = (0, 255, 0)  # BGR instead of RGB
BOX_W = 25
BOX_H = 25

img = cv2.imread('/home/furas/test/lenna.png')
height, width = img.shape[:2]

regions = cv2.selectROIs('Image', img)
print(regions)

for number, (x, y, w, h) in enumerate(regions, 1):
    x1 = x
    y1 = y
    x2 = x + BOX_W
    y2 = y + BOX_H
    data = img[y1:y2, x1:x2]
    result = data.mean()
    
    print(f'mean for [{y1:3}:{y2:3}, {x1:3}:{x2:3}]: {result:6.2f}')
            
    cv2.imshow(f"Crop {number}", data)
    
cv2.waitKey(0)

cv2.destroyAllWindows()

推荐阅读