>

파이썬을 처음 접했고 알고리즘의 일부를 병렬화하는 데 문제가 있습니다. 픽셀 레벨에서 특정 방식으로 임계 값이어야하는 입력 이미지를 고려하십시오. 알고리즘은 임계 값을 계산하기 위해 특정 영역 만 고려하기 때문에 별도의 스레드/프로세스에서 이미지의 각 청크를 실행하고 싶습니다. 그리고 이것은 내가 붙어있는 곳입니다. 이 스레드가 동일한 이미지에서 작동하거나 결과를 새 이미지로 병합하는 방법을 찾을 수 없습니다. 나는 보통 자바 세계에서 왔기 때문에 보통 다른 스레드를 방해하고 싶지 않은 문제와 싸우고 있습니다. 따라서 방금 각 프로세스에 이미지를 전달하려고했습니다.

def thresholding(img):
    stepSize = int(img.shape[0] / 10)
    futures = []
    with ProcessPoolExecutor(max_workers=4) as e:
        for y in range(0, img.shape[0], stepSize):
            for x in range(0, img.shape[1], stepSize):
                futures.append(e.submit(thresholdThread, y, x, img))
    concurrent.futures.wait(futures)
    return img

def thresholdThread(y, x, img):
    window_size = int(img.shape[0] / 10)
    window_shape = (window_size, window_size)
    window = img[y:y + window_shape[1], x:x + window_shape[0]]
    upper_bound, lower_bound, avg = getThresholdBounds(window, 0.6)
    for y_2 in range(0, window.shape[0]):
        for x_2 in range(0, window.shape[1]):
            tmp = img[y + y_2, x + x_2]
            img[y + y_2, x + x_2] = tmp if (tmp >= upper_bound or tmp <= lower_bound) else avg
    return str(avg)

파이썬을 이해하는 한, 각 프로세스마다 자체 img 사본을 가져 오기 때문에 작동하지 않습니다. . 그러나 img는 numpy에서 수레의 ndarray 유형이므로 공유 객체를 설명 된 여기 .

FYI : Python 3.6.9를 사용하고 있습니다. 3.7이 릴리스 된 것을 알고 있지만 스파이더를 사용할 수 있도록 다시 설치하면 openCV가 쉽지 않습니다.

  • 답변 # 1

    처리 시간을 크게 단축시킬 수있는 Numpy의 벡터화 기술을 사용하지 않습니다. 이것이 이미지의 창/청크에서 다중 처리 작업을 수행하려는 이유라고 가정합니다 .Docker가 무엇인지 알지 못하므로 다중 처리 방식의 요인인지 여부를 알 수 없습니다.

    여기서 작업에서 아래쪽 및 오른쪽 가장자리픽셀을 제외시킬 수있는 경고가있는 벡터화 된 솔루션이 있습니다. 그것이 허용되지 않으면 더 이상 읽을 필요가 없습니다.

    귀하의예에서 오른쪽 및 아래쪽 가장자리의 크기는 다른 창과 다를 가능성이 적습니다. 이미지를 청크하기 위해 임의로 10의 요소를 선택한 것처럼 보입니다. 10이 임의의 선택 인 경우 아래쪽 및 오른쪽 가장자리 델타를 쉽게 최적화 할 수 있습니다. 답의 끝에 해당 기능을 게시하겠습니다.

    작업을 벡터화하려면 이미지를 패치로재 형성해야합니다. 나는 sklearn 를 사용했습니다  기능 sklearn.feature_extraction.image._extract_patches  편리하고 겹치지 않는 패치 (원하는 것으로 보이는)를 만들 수 있기 때문입니다. 밑줄 접두어에 주목하십시오. 이것은노출함수 인 image.extract_patches 였습니다. 하지만 더 이상 사용되지 않습니다. 이 함수는 numpy.lib.stride_tricks.as_strided 를 사용합니다  -그냥 reshape 할 수 있습니다  배열을 시도했지만 시도하지 않았습니다.

    설정

    import numpy as np
    from sklearn.feature_extraction import image
    img = np.arange(4864*3546*3).reshape(4864,3546,3)
    # all shape dimensions in the following example derived from img's shape
    
    

    패치 크기 정의 ( opt_size 참조)  아래)와이미지를 수정합니다.

    hsize, h_remainder, h_windows = opt_size(img.shape[0])
    wsize, w_remainder, w_windows = opt_size(img.shape[1])
    # rgb - not designed for rgba
    if img.ndim == 3:
        patch_shape = (hsize,wsize,img.shape[-1])
    else:
        patch_shape = (hsize,wsize)
    patches = image._extract_patches(img,patch_shape=patch_shape,
                                     extraction_step=patch_shape)
    patches = patches.squeeze()
    
    

    patches  원본 배열에 대한 변경 내용은 원본에서 볼 수 있습니다. 그 모양은 (8, 9, 608, 394, 3) 입니다   8x9 가 있습니다 (608,394,3)  창/패치.

    각 패치의 상한과 하한을 찾으십시오. 각 픽셀을 패치의 경계와 비교하십시오. 경계 사이에 있고 변경해야하는 각 픽셀의 인덱스를 추출합니다.

    lower = patches.min((2,3)) * .6
    lower = lower[...,None,None,:]
    upper = patches.max((2,3)) * .6
    upper = upper[...,None,None,:]
    indices = np.logical_and(patches > lower, patches < upper).nonzero()
    
    

    각 패치의 평균을 찾은 다음 필요한 픽셀 값을 변경하십시오.

    avg = patches.mean((2,3))    # shape (8,9,3)
    patches[indices] = avg[indices[0],indices[1],indices[-1]]
    
    
    <시간>

    모든 것을 하나로 묶는 기능

    def g(img, opt_shape=False):
        original_shape = img.shape
        # determine patch shape   
        if opt_shape:
            hsize, h_remainder, h_windows = opt_size(img.shape[0])
            wsize, w_remainder, w_windows = opt_size(img.shape[1])
        else:
            patch_size = img.shape[0] // 10
            hsize, wsize = patch_size,patch_size
        # constraint checking here(?) for
        #     number of windows,
        #     orphaned pixels
        if img.ndim == 3:
            patch_shape = (hsize,wsize,img.shape[-1])
        else:
            patch_shape = (hsize,wsize)
        patches = image._extract_patches(img,patch_shape=patch_shape,
                                         extraction_step=patch_shape)
        #squeeze??
        patches = patches.squeeze()
        #assume color (h,w,3)
        lower = patches.min((2,3)) * .6
        lower = lower[...,None,None,:]
        upper = patches.max((2,3)) * .6
        upper = upper[...,None,None,:]
        indices = np.logical_and(patches > lower, patches < upper).nonzero()
        avg = patches.mean((2,3))
    ##    del lower, upper, mask
        patches[indices] = avg[indices[0],indices[1],indices[-1]]
    
    
    <시간>
    def opt_size(size):
        '''Maximize number of windows, minimize loss at the edge
        size -> int
           Number of "windows" constrained to 4-10
           Returns (int,int,int)
               size in pixels,
               loss in pixels,
               number of windows
        '''
        size = [(divmod(size,n),n) for n in range(4,11)]
        n_windows = 0
        remainder = 99
        patch_size = 0
        for ((p,r),n) in size:
            if r <= remainder and n > n_windows:
                remainder = r
                n_windows = n
                patch_size = p
        return patch_size, remainder, n_windows
    
    
    <시간>

    순진한프로세스에 대해 테스트되었습니다. 올바르게 실행했으면합니다. 4864x3546 색상이미지에서 약 35 배 향상되었습니다. 아마도 일부 마법사가 주석을 추가 할 수있는 추가 최적화가있을 수 있습니다.

    청크 요소 10을 사용하여 테스트 :

    #yours
    def f(img):
        window_size = int(img.shape[0] / 10)
        window_shape = (window_size, window_size)
        for y in range(0, img.shape[0], window_size):
            for x in range(0, img.shape[1], window_size):
                window = img[y:y + window_shape[1], x:x + window_shape[0]]
                upper_bound = window.max((0,1)) * .6
                lower_bound = window.min((0,1)) * .6
                avg = window.mean((0,1))
                for y_2 in range(0, window.shape[0]):
                    for x_2 in range(0, window.shape[1]):
                        tmp = img[y + y_2, x + x_2]
                        indices = np.logical_and(tmp < upper_bound,tmp > lower_bound)
                        tmp[indices] = avg[indices]
    
    img0 = np.arange(4864*3546*3).reshape(4864,3546,3)
    #get everything the same shape
    size = img0.shape[0] // 10
    h,w = size*10, size * (img0.shape[1]//size)
    img1 = img0[:h,:w].copy()
    img2 = img1.copy()
    assert np.all(np.logical_and(img1==img2,img2==img0[:h,:w]))
    f(img1)    # ~44 seconds
    g(img2)    # ~1.2 seconds
    assert(np.all(img1==img2))
    if not np.all(img2==img0[:h,:w]):
        pass
    else:
        raise Exception('did not change')
    
    
    <시간>

    indices  인덱스 배열입니다. 각 차원마다 하나씩 배열의 튜플입니다. 와이즈 비즈  3D 배열에서 하나의요소에 대한 색인입니다. 완전한 튜플을 사용하여 배열의 여러 요소를 색인 할 수 있습니다.

    indices[0][0],indices[1][0],indices[2][0]
    
    

    >>> indices (array([1, 0, 2]), array([1, 0, 0]), array([1, 1, 1])) >>> list(zip(*indices)) [(1, 1, 1), (0, 0, 1), (2, 0, 1)] >>> arr = np.arange(27).reshape(3,3,3) >>> arr[1,1,1], arr[0,0,1],arr[2,0,2] (13, 1, 20) >>> arr[indices] array([13, 1, 19]) # arr[indices] <-> np.array([arr[1,1,1],arr[0,0,1],arr[2,0,1]])  부울 배열과 np.logical_and(patches > lower, patches < upper) 를 반환합니다.  값이 nonzero() 인 모든 원소의 인덱스를 반환합니다. .

    True

  • 이전 linux - 특정 형식 단어를 다른 형식으로 바꿉니다
  • 다음 javascript - 모난 - 'dd/mm/yyyy hh : mm : ss'를 사용하여 날짜와 형식의 차이를 얻으십시오