Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Cython:view_as_windows与手动算法在Python中的性能?_Python_Algorithm_Performance_Numpy_Cython - Fatal编程技术网

Cython:view_as_windows与手动算法在Python中的性能?

Cython:view_as_windows与手动算法在Python中的性能?,python,algorithm,performance,numpy,cython,Python,Algorithm,Performance,Numpy,Cython,我的环境是OS:Ubuntu和语言:Python+Cython 我有点困惑,不知该走哪条路。我正在使用view_as_窗口对图像进行切片,并将切片创建的所有面片的数组返回给我。我还创建了一个算法,它可以做几乎相同的事情,对切片进行更多的控制。我已经测试了这两种算法,它们产生的结果正是我想要的,我现在的问题是我需要更快的性能,所以我正在尝试将这些东西进行cythonize。我是Cython的新手,所以我还没有做任何改变 按每个图像查看windows时间:0.0033s 每个图像的逐列修补时间:0.

我的环境是OS:Ubuntu和语言:Python+Cython

我有点困惑,不知该走哪条路。我正在使用view_as_窗口对图像进行切片,并将切片创建的所有面片的数组返回给我。我还创建了一个算法,它可以做几乎相同的事情,对切片进行更多的控制。我已经测试了这两种算法,它们产生的结果正是我想要的,我现在的问题是我需要更快的性能,所以我正在尝试将这些东西进行cythonize。我是Cython的新手,所以我还没有做任何改变

按每个图像查看windows时间:0.0033s

每个图像的逐列修补时间:0.057s


问题:

考虑到这些运行时间,我是通过将手动算法循环化来获得更好的性能,还是继续使用view_as_窗口? 我问这个问题是因为我认为我不能将view_视为_窗口,因为它是从numpy调用的。我使用禁用的可变步幅进行测试(步幅除数==0和imgRegion==0)。图像大小为1200 x 800

GetPatchesAndCoordByRow(手动代码)

参数:

#Patch Image Settings: Should be 3x2 ratio for width to height
WIDTH = 60
HEIGHT = 40
CHANNELS = 1
ITERATIONS = 7
MULTIPLIER = 1.31
#Stride will be how big of a step each crop takes.
#If you dont want to crops to overlap, do same stride as width of image.
STRIDE = 6
# STRIDE_IMREG_DIV decreases normal stride inside an image region
    #Set amount by which to divide stride.
        #Ex: 2 would reduce stride by 50%, and generate 200% data
        #Ex contd: So it would output 40K patches instead of 20K
    #strideDivisor = 1.5
# IMG_REGION determines what % of image region will produce additional patches
    #Region of image to focus by decreasing stride. Ex: 0.5 would increase patches in inner 50% of image
    #imgRegion = 0.5
# Set STRIDE_IMREG_DIV and IMG_REGION = 0 to disable functionality.
STRIDE_IMREG_DIV = 0
IMG_REGION = 0
源代码:

def setVarStride(x2, y2, maxX, maxY, stride, div, imgReg, var):
    imgFocReg1 = imgReg/2
    imgFocReg2 = 1 - imgFocReg1

    if (var == 'x'):
        if ((x2 >= maxX*imgFocReg1) and (x2 <= maxX*imgFocReg2) and (y2 >= maxY*imgFocReg1) and (y2 <= maxY*imgFocReg2)):
            vStride = stride/div
        else:
            vStride = stride
    elif (var == 'y'):
        if ((y2 >= maxY*imgFocReg1) and (y2 <= maxY*imgFocReg2)):
            vStride = stride/div
        else:
            vStride = stride
    return vStride

def GetPatchesAndCoordByRow(image, patchHeight, patchWidth, stride, strideDivisor, imgRegion):
    x1 = 0
    y1 = 0
    x2 = patchWidth
    y2 = patchHeight
    croppedImageList = []
    maxX, maxY = image.size

    #Set variable stride to collect more data in a region of the image
    varStride = stride
    useVaraibleStride = True
    if (strideDivisor == 0 and imgRegion == 0):
        useVaraibleStride = False
    else:
        imgConcentration = (1 - imgRegion)*100
        print("Variable Stride ENABLED: Create more patches inside {0}% of the image.".format(imgConcentration))

    while y2 <= (maxY):
        while x2 <= (maxX):
            croppedImage = image.crop((x1,y1,x2,y2))
            croppedImageList.append((croppedImage,(x1, y1, x2, y2)))
            #Get 2x more patches in the center of the image
            if (useVaraibleStride):
                varStride = setVarStride(x2, y2, maxX, maxY, stride, strideDivisor, imgRegion, 'x')
            #Rows
            x1 += varStride
            x2 += varStride
            #--DEBUG
            #iX += 1
            #print("Row_{4} -> x1: {0}, y1: {1}, x2: {2}, y2: {3}".format(x1, y1, x2, y2,iX))

        #Get 2x more patches in the center of the image
        if (useVaraibleStride):
            varStride = setVarStride(x2, y2, maxX, maxY, stride, strideDivisor, imgRegion, 'y')
        #Columns
        x1  = 0
        x2  = patchWidth
        y1 += varStride
        y2 += varStride
        #--DEBUG
        #iY += 1
        #print("    Column_{4} -> x1: {0}, y1: {1}, x2: {2}, y2: {3}".format(x1, y1, x2, y2, iY))

    #Get patches at edge of image
    x1 = 0
    x2 = patchWidth
    y1 = maxY - patchHeight
    y2 = maxY
    #Bottom edge patches
    while x2 <= (maxX):
        #--DEBUG
        #iX += 1
        #print("Row_{4} -> x1: {0}, y1: {1}, x2: {2}, y2: {3}".format(x1, y1, x2, y2,iX))
        #--DEBUG
        croppedImage = image.crop((x1,y1,x2,y2))
        croppedImageList.append((croppedImage,(x1, y1, x2, y2)))
        #Rows
        x1 += stride
        x2 += stride
    #Right edge patches
    x1 = maxX - patchWidth
    x2 = maxX
    y1 = 0
    y2 = patchHeight
    while y2 <= (maxY):
        #--DEBUG
        #iY += 1
        #print("    Column_{4} -> x1: {0}, y1: {1}, x2: {2}, y2: {3}".format(x1, y1, x2, y2, iY))
        #--DEBUG
        croppedImage = image.crop((x1,y1,x2,y2))
        croppedImageList.append((croppedImage,(x1, y1, x2, y2)))
        #Columns
        y1 += stride
        y2 += stride
    #--DEBUG
    print("GetPatchesAndCoordByRow (Count={0}, W={1}, H={2}, Stride={3})".format(len(croppedImageList), int(patchWidth), int(patchHeight), int(stride)))

    return croppedImageList

我不认为你能做得比
按窗口查看更好,因为只要输入数组是连续的,它就已经非常有效了。我怀疑,即使是把它简单化也会有很大的不同。我调查了它的实施情况,实际上有点印象深刻:

numpy数组由一个底层数据数组(如
char*
)和一个“步幅”数组组成,每个维度一个“步幅”数组,它告诉我们在该维度上的每一步要沿着底层数组移动多远。利用这一点,创建一个新数组,该数组与其输入共享相同的数据数组,并简单地插入新的“跨步”,以添加可用于选择修补程序的维度。这意味着它不会像您所说的那样返回“所有补丁的数组”,而是只返回一个数组,它的第一个维度就像一个补丁数组的索引

因此,
view\u as\u windows
不需要复制图像中的任何数据来创建修补程序,也不需要为每个修补程序创建额外的ndarray对象。它需要复制数据的唯一时间是当其输入数组不连续时(例如,它是较大数组的一个切片)。即使有Cython,我也看不出你能做得比这更好

在您的实现中,即使假定
image.crop
能够共享来自映像的数据,您仍然在创建一个看起来像1199x799个不同
image
对象的数组


您确认了算法大部分时间都花在
查看windows
上了吗?

我添加了其他信息,特别是用于调用函数的参数部分。这就是你可以看到这个函数在一个循环中,循环迭代7次,每次以6的步幅增加1.31倍的面片大小。因此,最终这两种算法都创建了大约20K个补丁。我创建手动算法的主要原因是为了保存每个面片的坐标。因此,我唯一关心的是在view_as_窗口外获得每个补丁的正确坐标。程序还有其他部分需要优化,但我每次都在使用
view\u as\u windows
,使用
numpy.linspace
(或者可能
numpy.arange
)来计算每个补丁的绝对坐标似乎会更快和
numpy.mgrid
而不是在纯python中使用
while
循环来计算它们。事实上,我认为您所需要的只是使用
numpy.mgrid[:宽度:跨步,:高度:跨步]
。为了获得绝对坐标…我以前从未使用过该函数,并且不熟悉如何将其与view_as_windows结合使用?如果不将数组传递给numpy.mgrid[:width:stride,:height:stride]如何在view\u as\u windows运行后将坐标返回给我?另外,宽度和高度是带有/高度的面片,而不是完整的图像尺寸。我查找了如何使用它的示例,但没有将其与view_as_windows结合使用的示例。正如您在[26]:coords Out[26]:array([[0,0,0,0],[10,10,10,10],[20,20,20],[30,30,30],[40,40],[20,20]中提到的@codewarrior
,iPython使用mgrid创建了此输出,[27]、[0,10,20,30]、[0,10,20,30]、[0,10,20,30]、[0,10,20,30]、[0,10,20,30]、[0,10,20,30]、[0,10,20,30]、[0,10,20,30]、[27]:coords.shape Out[27]:(2,6,4)
在[20]:patches.shape Out[20]:(117,75,40,60)
这意味着它创建了117x75块40x60像素的补丁。
def CreatePatches(image, patchHeight, patchWidth, stride = 1):
    imageArray = numpy.asarray(image)
    patches = view_as_windows(imageArray, (patchHeight, patchWidth), stride)
    print("Raw Patches initial shape: {0}".format(patches.shape))
    return patches