在两个图像的面片上计算函数的最快方法

时间:2019-05-31 09:53:53

标签: python image numpy numpy-ndarray

我有两个相等大小的图像,我想计算一个函数,让f假设在图像的块上,并在每个图像位置计算一个数字

补丁提取很容易

   patches1 = image.extract_patches_2d(img1,(5,5))
   patches2 = image.extract_patches_2d(img2,(5,5))

现在应用该功能可能如下所示

   result = numpy.zeros((image1.shape[0], img1.shape[1]))
   for i in range(len(image1.shape[0])):
       for j in range(len(image1.shape[0])):
           result[i,j] = f(patches1[i], patches1[j])

但这太慢了!!!

我想知道快速计算它并摆脱循环的最佳方法是什么。

谢谢

EDIT1:

f的实现是

    def f (patch1, patch2):
        return np.sqrt(patch1^2 + patch2^2)

2 个答案:

答案 0 :(得分:0)

您可以使用多重处理使其快速:

            #include <iostream>
        #include <sstream>
        #include <bitset>
        #include <vector>
        #include <iomanip>
        #include <cstring>
        #include <openssl/des.h>
        #include <stdlib.h>
        #include <string.h>

        using namespace std;


        int main(int argc, char* argv[])
        {

            DES_cblock cb1 = { 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE };
            DES_cblock cb2 = { 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE };
            DES_cblock cb3 = { 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE };

            DES_cblock cblock = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

            DES_key_schedule ks1,ks2,ks3;

           char string[] = "I am a software developer";
           // ---------------------------------------------
           // I use sizeof instead of strlen because I want
           // to count the '\0' at the end, strlen would
           // not count it
           int stringLen(sizeof(string));

           printf("Plain Text : %s\n",string);

           char* cipher(new char[32]);
           char* text(new char[stringLen]);
           memset(cipher,0,32);
           memset(text,0,stringLen);


           DES_set_odd_parity(&cblock);

           if (DES_set_key_checked(&cb1, &ks1) ||
                DES_set_key_checked(&cb2, &ks2) ||
                 DES_set_key_checked(&cb3, &ks3)) {
              printf("Key error, exiting ....\n");
              return 1;
           }

           DES_ede3_cbc_encrypt((const unsigned char*)string,
                                 (unsigned char*)cipher,
                                  stringLen, &ks1, &ks2, &ks3,
                                          &cblock, DES_ENCRYPT);
           printf("Encrypted : %32.32s\n",cipher);

           //-----------------------------------------------
           // You need to start with the same cblock value
           memset(cblock,0,sizeof(DES_cblock));
           DES_set_odd_parity(&cblock);

           //-----------------------------------------------
           // I think you need to use 32 for the cipher len.
           // You can't use strlen(cipher) because if there
           // is a 0x00 in the middle of the cipher strlen
           // will stop there and the length would be short
           DES_ede3_cbc_encrypt((const unsigned char*)cipher,
                                 (unsigned char*)text,
                                  32, &ks1, &ks2, &ks3,
                                             &cblock,DES_DECRYPT);
           printf("Decrypted : %s\n",text);


            return 0;
        }

通过优化f使之在整个from concurrent import futures import itertools import numpy as np patches1 = image.extract_patches_2d(img1,(5,5)) H = image.shape[0]; W = image.shape[1] results = np.zeros(H*W) with futures.ProcessPoolExecutor(max_workers=8) as exe: procs = {exe.submit(f, patches1[i], patches1[j]): i*W+j for (i,j) in itertools.product(range(H), range(W))} for r in futures.as_completed(procs): ids = procs[r] val = r.result() results[ids] = val results = np.reshape(results,(H,W)) 而非image上运行,可能有一种更聪明的方法。在这里,我仅显示一种工程方法。

答案 1 :(得分:0)

我对此进行了尝试-欢迎任何想对其代码进行基准测试的人复制我的初始化代码。基本上,它会创建一个标准化的图像,并将图像的黑色部分作为补丁A与白色部分作为补丁B进行比较。

enter image description here

#!/usr/local/bin/python3

import numpy as np
import math

# Generate a standardised "random" array
shape=(768,1024)                                                                        
np.random.seed(42)                                                                      
img = np.random.randint(0,256,shape,dtype=np.uint8) 

def loopy(patch1,patch2): 
    """Version with loops"""
    h, w = patch1.shape[0], patch1.shape[1] 
    result = np.zeros((h, w), dtype=np.float) 
    for i in range(h): 
        for j in range(w): 
            p1 = float(patch1[i,j]) 
            p2 = float(patch2[i,j]) 
            result[i,j] = math.sqrt(p1*p1+p2*p2) 
    return result 

def me(patch1,patch2): 
    A = patch1.astype(np.float) * patch1.astype(np.float) 
    B = patch2.astype(np.float) * patch2.astype(np.float)  
    return np.sqrt(A + B) 

# Run loopy and me and compare results
l = loopy(img[100:200,100:200],img[400:500,400:500])  
m = me(img[100:200,100:200],img[400:500,400:500])                                                                            
print(np.mean(m-l))

%timeit loopy(img[100:200,100:200],img[400:500,400:500])
# 5.73 ms ± 74.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit me(img[100:200,100:200],img[400:500,400:500])
# 40.2 µs ± 1.05 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)