python - 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.
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.
解决方案
如果你有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()
推荐阅读
- css - 将 Tr 从响应表中分离出来
- python - For循环读取文件名
- reactjs - 使用 react-localize-redux-translations 作为 yup-required-string
- c# - 从 Oracle 数据库中选择查询没有超时 - 通过 ADODB 互操作连接
- javascript - 如何默认选择特定页面?
- php - 在删除父级之前检查子级数据是否存在
- javascript - 避免保存重复记录 - Angular 6 - Mat-Table
- ios - 以 UTF-8 格式转换响应时出现问题
- c# - 如何将值设置为主对象内的嵌套属性
- mapbox - mapbox表达式中的匹配是精确匹配,如何在表达式中使用模糊匹配