首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用具有不同分位数的medianBlur

使用具有不同分位数的medianBlur
EN

Stack Overflow用户
提问于 2021-01-20 01:57:24
回答 2查看 143关注 0票数 1

我想对图像应用一个类似于medianBlur的函数,但不像medianBlur那样使用0.5分位数,我想应用另一个分位数(例如0.15)。

在我的玩具示例之外,我将对具有较大内核大小的1000x1000px图像使用此方法。

我写了一个实现(apply_quantileblur),它正在做我想做的事情,但毫不奇怪,它相当慢。

代码语言:javascript
复制
import cv2
import numpy as np
from matplotlib import pyplot as plt


img = np.array([[  6, 249, 255, 255, 255, 249,   0,   6, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255],
       [252,   3,  34, 255, 252, 255, 170, 255, 252, 135, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255],
       [  0,   0, 255, 255, 255, 255,  83, 255,   0, 255,   0, 255, 255,
        255, 255, 255, 255, 255, 255, 255],
       [255,   0,   0, 207, 255,  48, 255,  48, 255,  48, 255, 207, 255,
        255, 207, 255, 255, 255, 255, 255],
       [245, 245,  38,   0,   0, 255,  86,   9, 245, 255, 245,   9, 101,
        255, 245, 255, 255, 255, 255, 255],
       [  0, 255,  32, 255, 255,   0,   0,   0,   0,   0, 255, 255,   0,
        255, 255, 255, 255, 255, 255, 255],
       [255, 255,  32, 255, 255,   0,  83,   0, 255,   0,   0,   0, 255,
        255, 255, 255, 255, 255, 255, 255],
       [239, 239, 225,   0, 239, 255, 239,   0,   0, 141,   0,   0, 255,
        255, 239,  15, 255, 255, 255, 255],
       [  0,   0, 201,  25, 255, 255, 229,   0,  25,   0, 229,  25,  25,
        229, 229,   0, 255, 255, 255, 255],
       [  0,   0,   0,   0,   0,   0, 172,   0, 255,   0,   0, 255, 255,
          0, 255, 255, 255, 255, 255, 255],
       [120, 255, 117,   0, 120, 255, 134,   0,   0,  64, 255,   0, 134,
        120, 120, 120, 255, 255, 255, 255],
       [ 76,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  76,  28,
          0,   0,  76,  76,  76,  76, 255],
       [  0,   0, 223,   0,   0,   0,  83,   0,   0,   0,   0,   0,   0,
          0, 255, 255,   0, 255, 255, 255],
       [255, 210,  45,   0,  45,  45,  45,  45,  45,  23,   0,   0,   0,
         45,  45,  45, 210, 255, 255, 255],
       [ 89,   0, 255, 255,   0, 255, 141, 165, 165,  42, 165, 165,  89,
          0, 165,  89, 255, 255, 255, 255],
       [255, 255,  11,  12,  12, 255, 255, 255,   0, 255,  12,   0, 242,
        255, 255, 255, 255, 255, 255, 255],
       [255, 255, 246,   9, 245, 245, 255,   9, 255,   5, 245, 255, 255,
        255, 255, 255, 255, 255, 255, 255],
       [  0,   0,   0,   0,   0,   0,   0,   0,   0, 134, 255,   0,   0,
        255, 255, 255, 255, 255, 255, 255],
       [255, 217, 228, 255, 255,  38, 255, 255, 217, 121, 255, 255, 231,
        255, 255, 255, 255, 255, 255, 255],
       [255, 255, 230, 255,   0, 226, 255, 255, 255, 255, 255, 255, 255,
        255, 255, 255, 255, 255, 255, 255]]).astype(np.uint8)

    

plt.imshow(img)
plt.title('original image')
plt.show()

median_blurred_img = cv2.medianBlur(img, 5)
plt.imshow(median_blurred_img)
plt.title('median blurred image')
plt.show()


def apply_quantileblur(img, kernel_size, quantile):
    rows, cols = img.shape
    newmat = np.zeros((rows, cols))
    kerny = int((kernel_size - 1) / 2)
    for r in range(rows):
        rmin = max(r - kerny, 0)
        rmax = min(r + kerny + 1, rows)

        for c in range(cols):
            cmin = max(c - kerny, 0)
            cmax = min(c + kerny + 1, cols)

            miniimg  = img[rmin:rmax, cmin:cmax]
            newmat[r, c] = np.quantile(miniimg, quantile)

    return newmat

quantile_blurred_img = apply_quantileblur(img, 5, 0.15)
plt.imshow(quantile_blurred_img)
plt.title('0.15 quantile blurred image')
plt.show()

quantile_blurred_img = apply_quantileblur(img, 5, 0.85)
plt.imshow(quantile_blurred_img)
plt.title('0.85 quantile blurred image')
plt.show()

以下哪项输出:

由于medianBlur正在做一件非常类似的事情,大约快1000倍,我想知道如何改进这个过程,使其真正可用。

编辑:

到目前为止,我已经比较了4种不同的方法:

代码语言:javascript
复制
from scipy.ndimage import generic_filter
import time
import diplib
# sudo apt install default-jre
# sudo apt-get install freeglut3
import cv2
import numpy as np
from matplotlib import pyplot as plt

def show_img(img, title):
    plt.imshow(img)
    plt.title(title)
    plt.show()


def apply_quantileblur_manual(img, kernel_size, quantile):
    rows, cols = img.shape
    newmat = np.zeros((rows, cols))
    kerny = int((kernel_size - 1) / 2)
    for r in range(rows):
        rmin = max(r - kerny, 0)
        rmax = min(r + kerny + 1, rows)

        for c in range(cols):
            cmin = max(c - kerny, 0)
            cmax = min(c + kerny + 1, cols)

            miniimg  = img[rmin:rmax, cmin:cmax]
            newmat[r, c] = np.quantile(miniimg, quantile)

    return newmat


def apply_quantileblur_generic(img, kernel_size, quantile):
    return generic_filter(img, lambda x: np.quantile(x, quantile), size=kernel_size)


def medianblur(img, kernel_size):
    return cv2.medianBlur(img, kernel_size)

def diplib_blur(img, kernel_size, quantile):
    k = diplib.Kernel([kernel_size,kernel_size])
    z = diplib.PercentileFilter(img, quantile, k)
    return z

img = np.random.randint(0,255,(500, 500), np.uint8)
cv2.imwrite('ugh.tiff', img)
dip_img = diplib.ImageReadTIFF('ugh.tiff')

kernel_size = 111
quantile = 50

start = time.time()
manual_img = apply_quantileblur_manual(img, kernel_size, quantile / 100)
print(time.time() - start)

start = time.time()
generic_img = apply_quantileblur_generic(img, kernel_size, quantile / 100)
print(time.time() - start)

start = time.time()
median_img = medianblur(img, kernel_size)
print(time.time() - start)

start = time.time()
diplib_img = diplib_blur(img, kernel_size, quantile)
print(time.time() - start)

打印的内容:

代码语言:javascript
复制
31.994836568832397
46.67619204521179
0.005266904830932617
1.999727725982666

所以OpenCV实际上快了10.000,但是没有指定分位数的选项。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-01-31 00:57:40

scipy.ndimage库中有一个函数可以执行您所要求的操作:percentile_filter

代码语言:javascript
复制
from scipy.ndimage import percentile_filter
percentile_blur = percentile_filter(img, percentile=20, size=15)

generic_filter实现相比,您可以预期性能提升40倍。

票数 3
EN

Stack Overflow用户

发布于 2021-01-20 02:19:19

可以使用generic_filter()重写您的函数

代码语言:javascript
复制
from scipy.ndimage import generic_filter

def apply_quantileblur(img, kernel_size, quantile):
    return generic_filter(img, lambda x: np.quantile(x, quantile), size=kernel_size)

文档:https://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.generic_filter.html

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65796927

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档