使用Python,我必须:
Test_Image
和Reference_image
划分为5x5块,image1(1,1)
image2(1,1)
。 到目前为止,我使用hist=numpy.histogram(image,bins=256)
我想分割图像,然后计算所有这些块的直方图。我也想用Bhattacharya的系数来衡量相似性。
任何人都可以指导我如何通过这个吗?在此先感谢:)
答案 0 :(得分:13)
不确定您是否正在寻找这样的东西, 这是蛮力版本。它可能很慢。但是它完成了这项工作 你必须决定如何处理边界。 除非窗口完全符合
,否则不包括边界import numpy as numpy
grey_levels = 256
# Generate a test image
test_image = numpy.random.randint(0,grey_levels, size=(11,11))
# Define the window size
windowsize_r = 5
windowsize_c = 5
# Crop out the window and calculate the histogram
for r in range(0,test_image.shape[0] - windowsize_r, windowsize_r):
for c in range(0,test_image.shape[1] - windowsize_c, windowsize_c):
window = test_image[r:r+windowsize_r,c:c+windowsize_c]
hist = numpy.histogram(window,bins=grey_levels)
以下是结果,完整图像结束。 r,c代表窗口的顶角
r=0,c=0
[[ 63 173 131 205 239]
[106 37 156 48 81]
[ 85 85 119 60 228]
[236 79 247 1 206]
[ 97 50 117 96 206]]
r=0,c=5
[[108 241 155 214 183]
[202 2 236 183 225]
[214 141 1 185 115]
[ 4 234 249 95 67]
[232 217 116 211 24]]
r=5,c=0
[[179 155 41 47 190]
[159 69 211 41 92]
[ 64 184 187 104 245]
[190 199 71 228 166]
[117 56 92 5 186]]
r=5,c=5
[[ 68 6 69 63 242]
[213 133 139 59 44]
[236 69 148 196 215]
[ 41 228 198 115 107]
[109 236 191 48 53]]
[[ 63 173 131 205 239 108 241 155 214 183 42]
[106 37 156 48 81 202 2 236 183 225 4]
[ 85 85 119 60 228 214 141 1 185 115 80]
[236 79 247 1 206 4 234 249 95 67 203]
[ 97 50 117 96 206 232 217 116 211 24 242]
[179 155 41 47 190 68 6 69 63 242 162]
[159 69 211 41 92 213 133 139 59 44 196]
[ 64 184 187 104 245 236 69 148 196 215 91]
[190 199 71 228 166 41 228 198 115 107 82]
[117 56 92 5 186 109 236 191 48 53 65]
[177 170 114 163 101 54 80 25 112 35 85]]
答案 1 :(得分:2)
如果图像很大,可以通过操纵数组的步幅来生成所需的 windows ,从而提高性能。以下将使用Efficient Overlapping Windows with Numpy处的广义滑动窗口函数 - 我将在最后包含它。
import numpy as np
image1 = np.arange(100).reshape(10,10)
image2 = np.arange(100).reshape(10,10)
from itertools import izip
window_size = (5,5)
windows1 = sliding_window(image1, window_size)
windows2 = sliding_window(image2, window_size)
histograms = [(np.histogram(window1,bins=256),np.histogram(window2,bins=256))
for window1, window2 in izip(windows1, windows2)]
for h1, h2 in histograms:
print np.all(h1[0] == h2[0])
滑动窗口功能:
from numpy.lib.stride_tricks import as_strided as ast
from itertools import product
def norm_shape(shape):
'''
Normalize numpy array shapes so they're always expressed as a tuple,
even for one-dimensional shapes.
Parameters
shape - an int, or a tuple of ints
Returns
a shape tuple
'''
try:
i = int(shape)
return (i,)
except TypeError:
# shape was not a number
pass
try:
t = tuple(shape)
return t
except TypeError:
# shape was not iterable
pass
raise TypeError('shape must be an int, or a tuple of ints')
def sliding_window(a,ws,ss = None,flatten = True):
'''
Return a sliding window over a in any number of dimensions
Parameters:
a - an n-dimensional numpy array
ws - an int (a is 1D) or tuple (a is 2D or greater) representing the size
of each dimension of the window
ss - an int (a is 1D) or tuple (a is 2D or greater) representing the
amount to slide the window in each dimension. If not specified, it
defaults to ws.
flatten - if True, all slices are flattened, otherwise, there is an
extra dimension for each dimension of the input.
Returns
an array containing each n-dimensional window from a
from http://www.johnvinyard.com/blog/?p=268
'''
if None is ss:
# ss was not provided. the windows will not overlap in any direction.
ss = ws
ws = norm_shape(ws)
ss = norm_shape(ss)
# convert ws, ss, and a.shape to numpy arrays so that we can do math in every
# dimension at once.
ws = np.array(ws)
ss = np.array(ss)
shape = np.array(a.shape)
# ensure that ws, ss, and a.shape all have the same number of dimensions
ls = [len(shape),len(ws),len(ss)]
if 1 != len(set(ls)):
raise ValueError(\
'a.shape, ws and ss must all have the same length. They were %s' % str(ls))
# ensure that ws is smaller than a in every dimension
if np.any(ws > shape):
raise ValueError('ws cannot be larger than a in any dimension. a.shape was %s and ws was %s' % (str(a.shape),str(ws)))
# how many slices will there be in each dimension?
newshape = norm_shape(((shape - ws) // ss) + 1)
# the shape of the strided array will be the number of slices in each dimension
# plus the shape of the window (tuple addition)
newshape += norm_shape(ws)
# the strides tuple will be the array's strides multiplied by step size, plus
# the array's strides (tuple addition)
newstrides = norm_shape(np.array(a.strides) * ss) + a.strides
strided = ast(a,shape = newshape,strides = newstrides)
if not flatten:
return strided
# Collapse strided so that it has one more dimension than the window. I.e.,
# the new array is a flat list of slices.
meat = len(ws) if ws.shape else 0
firstdim = (np.product(newshape[:-meat]),) if ws.shape else ()
dim = firstdim + (newshape[-meat:])
# remove any dimensions with size 1
dim = filter(lambda i : i != 1,dim)
return strided.reshape(dim)
如果要将图像分为四个部分,则需要计算ws
和ss
参数。如果两个维度均可被2整除,则ws
和ss
具有相同的值(ss
默认为ws
未指定时)。 Numpy能够将数组维度视为(列,行)或(行,列) - 我没有改变任何默认值,我的是(行,列)。对于18x26图片,ws = (26/2, 18/2)
- 每个窗口将为13x9,并且相邻的窗口通过 siliding 窗口获得相等的数量,不重叠。如果维度不能被2除,则还需要确定ss
,并且窗口中会有一些重叠。对于18x33图像:
>>>
>>> rows = 33
>>> columns = 18
>>> divisor = 2
>>> col_size, col_overlap = divmod(columns, divisor)
>>> row_size, row_overlap = divmod(rows, divisor)
>>> ws = (row_size, col_size)
>>> ss = (row_size - row_overlap, col_size - col_overlap)
>>> ws, ss
((16, 9), (15, 9))
>>>
对于3d窗口(来自具有颜色维度的图像的数据)ws
和ss
需要具有三个维度。 15x15图像将具有9个5x5x3窗口
from PIL import Image
import numpy as np
img = Image.open('15by15.bmp')
a = np.asarray(img)
window_size = (5,5,3)
windows = sliding_window(a, window_size)
print windows.shape
>>> (9, 5, 5, 3)
for window in windows:
print window.shape
>>> (5, 5, 3) (5, 5, 3) (5, 5, 3) (5, 5, 3) (5, 5, 3) (5, 5, 3) (5, 5, 3) (5, 5, 3) (5, 5, 3)
答案 2 :(得分:1)
我已将此代码编写为两个自动将图像拆分为n行和m列的代码。 m和n是自变量,很容易修改。之后,很容易为每个块计算直方图,这些直方图也保存到名为patchs的文件夹中。
# Image path, number of rows
# and number of columns
# should be provided as an arguments
import cv2
import sys
import os
if not os.path.exists('patches'):
os.makedirs('patches')
nRows = int(sys.argv[2])
# Number of columns
mCols = int(sys.argv[3])
# Reading image
img = cv2.imread(sys.argv[1])
#print img
#cv2.imshow('image',img)
# Dimensions of the image
sizeX = img.shape[1]
sizeY = img.shape[0]
print(img.shape)
for i in range(0,nRows):
for j in range(0, mCols):
roi = img[i*sizeY/nRows:i*sizeY/nRows + sizeY/nRows ,j*sizeX/mCols:j*sizeX/mCols + sizeX/mCols]
cv2.imshow('rois'+str(i)+str(j), roi)
cv2.imwrite('patches/patch_'+str(i)+str(j)+".jpg", roi)
cv2.waitKey()
答案 3 :(得分:0)
这对我有用。它具有划分为n * m个块的能力。相应地填充图像。
def chunkify(img, block_width=4, block_height=4):
shape = img.shape
x_len = shape[0]//block_width
y_len = shape[1]//block_height
chunks = []
x_indices = [i for i in range(0, shape[0]+1, block_width)]
y_indices = [i for i in range(0, shape[1]+1, block_height)]
shapes = list(zip(x_indices, y_indices))
for i in range(len(shapes)):
try:
start_x = shapes[i][0]
start_y = shapes[i][1]
end_x = shapes[i+1][0]
end_y = shapes[i+1][1]
chunks.append( shapes[start_x:end_x][start_y:end_y] )
except IndexError:
print('End of Array')
return chunks
https://github.com/QuantumNovice/ImageProcessing/blob/master/image_chunkify.py
答案 4 :(得分:-1)
要将正方形图像划分为正方形块(每个轴具有相同的块数),我使用了此方法(完整存储库here):
def blockDivide(img, blockNumber):
imgArray = np.array(Image.open(img))
# Define dimension of image
dimension = imgArray.shape[0]
# Set number of slices per axis
axisSlice = int(math.sqrt(blockNumber))
# Size of each block
arraySize = int(dimension / axisSlice)
# Shape of numpy array to be filled
blocksArray = np.zeros((arraySize, arraySize, blockNumber))
# Split the image into vertical blocks
split_a = np.split(imgArray, axisSlice, axis = 0)
# Set counter to zero
counter = 0
for i in range(axisSlice):
for j in range(axisSlice):
# Split vertical blocks into square blocks
split_b = np.split(split_a[i], axisSlice, axis = 1)
# Fill array with blocks
blocksArray[:, :, counter] = split_b[j]
# Increase counter
counter += 1
return blocksArray