在python中将图像分成5x5个块,并计算每个块的直方图

在python中将图像分成5x5个块,并计算每个块的直方图,python,python-2.7,image-processing,computer-vision,python-idle,Python,Python 2.7,Image Processing,Computer Vision,Python Idle,使用Python,我必须: 将测试图像和参考图像分为5x5个块 计算每个块的直方图,并将其与另一幅图像中的相同块进行比较。 例如:image1(1,1)withimage2(1,1) 比较两幅图像之间的相似性(应为变换不变) 到目前为止,我已经使用hist=numpy.histogram(image,bins=256) 我想分割一幅图像,然后计算所有这些块的直方图。我还想用Bhattacharya的系数来衡量相似性 有谁能指导我如何度过这一关吗?提前感谢:)不确定您要找的是不是这样的东西,

使用Python,我必须:

  • 测试图像
    参考图像
    分为5x5个块
  • 计算每个块的直方图,并将其与另一幅图像中的相同块进行比较。
    例如:
    image1(1,1)
    with
    image2(1,1)
  • 比较两幅图像之间的相似性(应为变换不变)
到目前为止,我已经使用
hist=numpy.histogram(image,bins=256)

我想分割一幅图像,然后计算所有这些块的直方图。我还想用Bhattacharya的系数来衡量相似性


有谁能指导我如何度过这一关吗?提前感谢:)

不确定您要找的是不是这样的东西, 这是蛮力版本。它可能相当慢。但它能完成任务 不过,你必须决定如何处理边界。 这将不包括边界,除非窗完全适合

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]]

如果图像较大,可以通过操纵阵列的步长来生成所需的窗口,从而提高性能。下面将使用一个通用的滑动窗口函数,该函数在-I中找到,我将在末尾包含它

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])
滑动窗口功能:

如果要将图像分成四部分,则需要计算
ws
ss
参数。如果两个维度都可以被二整除,则
ws
ss
是相同的值(
ss
未指定时默认为
ws
)。Numpy能够将数组维度视为(列,行)或(行,列)-我没有更改任何默认值,我的是(行,列)。对于18x26图片,
ws=(26/2,18/2)
-每个窗口将为13x9,相邻窗口通过将窗口平铺相等数量而获得,没有重叠。如果维度不能被二除,则还需要确定
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)

这对我有用。它可以分成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

我已经编写了这段代码,两个自动将图像分割成n行和m列。m和n是参数,很容易修改。之后,很容易计算每个块的直方图,这些直方图也保存到名为patches的文件夹中

# 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()

为了将方形图像划分为方形块(每个轴的块数相同),我使用了以下方法(完整存储库):


不清楚你在问什么。您是在问如何计算5x5区域的直方图,还是在问如何使用Bhattacharya系数来衡量相似性?如果你写了一个清晰而具体的问题(只有一个问题),其中包含了人们可以玩的最简单的工作示例,你将有更高的机会得到一个好答案。@kkuilla-我必须计算两幅图像之间的相似性,因为我必须将这些图像划分为5 x 5个区域,并计算每个区域的直方图。两幅图像将被划分为5 x 5个区域。然后,我将比较图像1中的每个块与另一个图像上的相应块。我说清楚了吗?嗯,我有点明白你想做什么,但我还是不知道你的问题是什么。嗯Thanks@kkuilla我需要一个如何将图像分割为多个部分的示例。请参见此答案。它包括一个函数和一个指向源的链接,用于从numpy数组生成窗口。搜索numpy和滑动窗口应该会产生类似的结果。-谢谢。感谢您的帮助,帮了我一个大忙。顺便问一下,您能告诉我如何在我的窗口中创建我的图像吗?@穆罕默德·阿利埃拉赫拉斯(Mohamed AliElakhrass)表示歉意,但我不明白。您的窗口是图像的子集,因此窗口仅为原始图像的5x5个部分。你知道每个窗口的坐标,所以你只要把它们拼回来就行了together@wwii-谢谢你的帮助,但是我想要的是把一张图片分成4部分。我有两张图片要比较。我想将两幅图像分成4部分,然后将每个部分的直方图与对应的其他部分进行比较。这里我有两张同样大小的图片。假设我想dic=将此图像分为4个部分如何操作?如果使用上面的
滑动窗口()
函数,则需要计算
ws
ss
参数的正确值。我将在答案中添加一个示例。@wwii我正在使用上述代码的初始部分获取图像块。然后我尝试以下操作:
window\u size=(100100)windows=sw.wi=Image.fromarray(w)io.imshow(wi)
但它不起作用。我听说窗户里有个虫子。是否还有其他窗口可以显示该窗口生成的图像修补程序?@user961627-您应该将其作为一个单独的问题发布,我不知道您正在使用哪些模块,但基本上您需要将每个窗口
ndarray
转换为图像并显示。@user961627-使用PIL我刚刚尝试
image.fromarray(w).save('foo.png'))
在循环中,它保存了我以后可以查看的所有窗口。要在飞行中看到它们,您可能必须在某种画布上绘制它们,可能
matplotlib
。这可能会有所帮助-虽然此链接可以回答问题,但最好在此处包含答案的基本部分,并提供链接供参考。如果链接页面发生更改,则仅链接的答案可能无效-
# 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()
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