使用Python和Numpy创建原始图像的图像切片(m*n)

rsl1atfo  于 2022-11-10  发布在  Python
关注(0)|答案(6)|浏览(125)

我正在使用NumPy从我的16位TIFF图像(1377716004)创建(224x224)的平铺。我能够沿着行和列裁剪/切片成相等的224224平铺。我在尝试创建新的瓷砖时遇到了问题,将瓷砖大小移动了一半……例如:我试图实现的粗略算法
(1:224,1:224)
(1:224,112:336)
(,224:448)
目标是保持平铺大小(224*224),同时平移平铺大小的一半,以获得更多的图像平铺...
为执行任务而编写的代码片段

row_x =  img.shape[0]
column_y = img.shape[1]

tile_size_x = 224
tile_size_y = 224

range_x = mpz(ceil(row_x/tile_size_x))
range_y = mpz(ceil(column_y/tile_size_y))

for x in range(range_x, row_x):

    for y in range(range_y, column_y): 

        x0 = x * tile_size_x 

        x1 = int(x0/2) + tile_size_x

        y0 = y * tile_size_y 

        y1 = int(y0/2) + tile_size_y

        z = img[x0:x1, y0:y1]
        print (z.shape,z.dtype)

我总是得到错误的结果,有谁能帮忙吗?

vktxenjb

vktxenjb1#

在计算for循环的范围时,您出现了一些偏差。要制作的切片的数量必须使用两个切片之间的偏移量来计算,在您的例子中是x0/2,我已经简化了您的代码并定义了一些有意义的变量,您可以配置这些变量来从给定的图像中获得所需的切片:

import cv2
import math

img = cv2.imread("/path/to/lena.png") # 512x512

img_shape = img.shape
tile_size = (256, 256)
offset = (256, 256)

for i in xrange(int(math.ceil(img_shape[0]/(offset[1] * 1.0)))):
    for j in xrange(int(math.ceil(img_shape[1]/(offset[0] * 1.0)))):
        cropped_img = img[offset[1]*i:min(offset[1]*i+tile_size[1], img_shape[0]), offset[0]*j:min(offset[0]*j+tile_size[0], img_shape[1])]
        # Debugging the tiles
        cv2.imwrite("debug_" + str(i) + "_" + str(j) + ".png", cropped_img)

作为当前偏移量,如果图像尺寸的精确倍数为512x512,则我们将得到4个相同大小的瓷砖:

更改偏移量的值将得到不规则大小的瓷砖,如果偏移量不是图像尺寸的精确倍数,则可以稍后通过在for循环中将math.ceil更改为math.floor来过滤这些瓷砖。

ttp71kqs

ttp71kqs2#

我认为您可以非常有效地使用as_strided

def window_nd(a, window, steps = None):
    ashp = np.array(a.shape)
    wshp = np.array(window).reshape(-1)
    if steps:
        stp = np.array(steps).reshape(-1)
    else:
        stp = np.ones_like(ashp)
    astr = np.array(a.strides)
    assert np.all(np.r_[ashp.size == wshp.size, wshp.size == stp.size, wshp <= ashp])
    shape = tuple((ashp - wshp) // stp + 1) + tuple(wshp)
    strides = tuple(astr * stp) + tuple(astr)
    as_strided = np.lib.stride_tricks.as_strided
    aview = as_strided(a, shape = shape, strides = strides)
    return aview

**编辑:**尽可能泛化跨步方法。

对于您的特定问题:

aview = window_nd(a, (288, 288), (144, 144))
z = aview.copy().reshape(-1, wx, wy) #to match expected output
print(z.shape, z.dtype) # z.shape should be (num_patches, 288, 288)
pokxtpni

pokxtpni3#

我想你可以用这个

def TileImage(image,rows,cols):
imagename = image
im = Image.open(imagename) 
width, height = im.size
indexrow = 0
indexcolum = 0
left = 0
top = 0
right = width/col
buttom = 0
while(right<=width):    
    buttom = height/rows
    top = 0
    indexrow=0  

    while(top<height):
        print(f"h : {height}, w : {width}, left : {left},top : {top},right : {right}, buttom   :  {buttom}")
        cropimg= im.crop((left, top, right, buttom)) 
        cropimg.save(imagename + str(indexrow) + str(indexcolum) +".jpg")
        top = buttom
        indexrow += 1
        buttom += height/rows   

    indexcolum+=1
    left = right
    right += width/col
jc3wubiy

jc3wubiy4#

如果您不介意使用ImageMagick,那么使用-crop命令就很简单了。请参阅https://imagemagick.org/Usage/crop/#crop_tile
您可以使用Python子进程调用来调用Imagemagick。
输入:

为了简单起见,假设您想要4个256x256的瓷砖。

convert lena512.png -crop 256x256 lena512_%d.png

或按百分比

convert lena512.png -crop 50x50% lena512_%d.png

oyxsuwqo

oyxsuwqo5#

我更喜欢事先计算瓷砖的数量,然后使用简单的重塑。例如

tile = 512
img_height = img.shape[1]
img_width = img.shape[0]
number_of_vertical_tiles = img_height // tile
number_of_horizontal_tiles = img_width // tile
cropped_img = img[:tile*number_of_vertical_tiles, :tile*number_of_horizontal_tiles,:]
tiled_img = img.reshape(-1, tile, tile, 3)
vlf7wbxs

vlf7wbxs6#

由于我的声誉滞后,我不被允许在@Zdar的顶部答案下发表评论。然而,代码非常适合我的用例,我想对CV2中的Python3和颜色通道进行必要的更改。谢谢你,“兹达尔。”
这是他在读写图片时使用list(range())而不是xrange()和cv2.COLOR_BGR2RGB为Python3改编的代码。不知何故,CV2以相反的方式使用这些频道。

img = cv2.cvtColor(cv2.imread("path/to/lena.png"),cv2.COLOR_BGR2RGB)
img_shape = img.shape
tile_size = (640, 640)
offset = (640, 640)

for i in list(range(int(math.ceil(img_shape[0]/(offset[1] * 1.0))))):
    for j in list(range(int(math.ceil(img_shape[1]/(offset[0] * 1.0))))):
        cropped_img = img[offset[1]*i:min(offset[1]*i+tile_size[1], img_shape[0]), offset[0]*j:min(offset[0]*j+tile_size[0], img_shape[1])]
        # Debugging the tiles
        cv2.imwrite("debug_" + str(i) + "_" + str(j) + ".png", cv2.cvtColor(cropped_img,cv2.COLOR_BGR2RGB))

相关问题