简体   繁体   中英

Shifting an array in a special location using numpy.roll

I have a 256x256 array I want to shift to the right using special row and column. I am using numpy.roll to achieve it. If I use the following code, shift is one column to the right.

import cv2
import matplotlib.pyplot as plt
import numpy as np

# Input (256x256 0 values array)
array = np.zeros((256,256))

# Draw a square inside the array (1 values)
array[100:156,100:156] = 1

# Shift the square to the right (1 as shift value)
shifted_array = np.roll(array,1)

If I repeat the process infinitely, it moves on the whole width of the array (256 columns) and then restart. What I want to do is shifting the array from column 120 to 130. It means that max shifting is 10 columns (not 256 like before). How can I achieve that?

[RESOLVED] Finally, I found a way to achieve that using the following code:

import cv2
import matplotlib.pyplot as plt
import numpy as np

# Input (256x256 0 values array)
array = np.zeros((256,256))

# Draw a square inside the array (1 values)
array[100:156,100:156] = 1

# Cropping the image between columns 120 and 130
cropped_image = array[:,120:130]

# Loop to shift the image every column and get the original dimensions  
i = 1
shift_value = 1

while i < len(cropped_image):
    shifted_array = np.roll(cropped_image, shift_value)
    shift_value = shift_value + 1
    i = i + 1
    new_array = np.zeros(array.shape)
    new_array[:,120:130] = shifted_array

The while loop above isn't doing anything. array never changes it's state so only the final iteration is saved in shifted_array. Below uses a smaller array to see the results.

import numpy as np

arr = np.zeros((12,12), dtype=np.int)
arr[ 4:8, 6:10]  = 1
arr
# array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0],
#        [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0],
#        [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0],
#        [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

crop = np.s_[:, 5:11]  # crop is the selection to roll.

new_array = np.zeros_like(arr)
new_array[crop] = np.roll(arr[crop], len(arr)-1)

new_array
# array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
#        [0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
#        [0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
#        [0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

This has the effect of moving the square down two rows and left one column.

Depending on what you are trying to achieve it may be better to explore using the axis parameter to np.roll(arr, 1, axis=1) to explicitly roll left/right and or axis=0 to roll up/down.

Thanks Tls Chris.

Indeed, it is not really the expected result but I just need to shift the square. My goal is to compare two images (imageA with a centered square, imageB with a shifted square) and shifting imageB's square in order to match imageA's square.

To detect the matching position, I use Fast Fourier Transform (FFT) as shown below. Then, I compute the difference between the two resulted images. If difference is equal to 0, then, matching position is found. So I succeed to find it using the code below.

import cv2
import matplotlib.pyplot as plt
import numpy as np

img1 = np.zeros((256,256))
img1[100:156,100:156] = 1

img2 = np.zeros(img1.shape)
img2[50:255, 50:255] = img1[:205,:205]

f = np.fft.fft2(img1)
fshift1 = np.fft.fftshift(f)

f = np.fft.fft2(img2)
fshift2 = np.fft.fftshift(f)

cropped_image = img2[90:220, 90:220]

i = 0
shift_value = 1
min_diff = 1000000000

while i < np.size(cropped_image):
    img3 = np.roll(cropped_image, shift_value)
    shift_value = shift_value + 1
    img4 = np.zeros(img1.shape)
    img4[90:220, 90:220] = img3
    f = np.fft.fft2(img4)
    fshift3 = np.fft.fftshift(f)
    real_value = np.sum(np.abs(np.real(fshift1) - np.real(fshift3)))
    if min_diff > real_value:
        min_diff = real_value
        print(i)
    i = i + 1

print(min_diff)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM