首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用OpenCv的阈值?

使用OpenCv的阈值?
EN

Stack Overflow用户
提问于 2020-01-10 02:45:41
回答 2查看 1K关注 0票数 0

如问题所述,我想将双向自适应阈值技术应用到我的图像中.也就是说,我想找出邻域中的每个像素值,如果它小于或大于邻域的平均值减去一个常数c,就将其设置为255。

以这张图像为例,作为像素的邻域。需要保留的像素区域是第三和第六正方形上半部(从左到右、从上到下)较暗的区域,以及八个和十二个方块的上半部。

显然,这都取决于设定的常量值,但理想情况下,与邻域的平均像素值明显不同的区域将被保留。不过,我自己也可以担心调音。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-01-10 07:14:14

你的问题和评论是相互矛盾的:保持每件事物(显着地)明亮/黑暗,比邻里的平均(+/-常数)(问题)和将一切保持在平均值+/常量(评论)内。我假设第一个答案是正确的,我将尝试给出一个答案。

使用cv2.adaptiveThreshold当然是有用的;参数化可能很棘手,特别是考虑到示例图像。首先,让我们看看输出:

我们看到,在给定的图像中,强度值的范围很小。第三和第六广场的上半部分和他们的邻里并没有什么不同。那里不太可能找到适当的区别。正方形#8和#12的上半部分(或方格#10的下半部分)更容易被找到。

顶部行现在显示更多的“全局”参数(blocksize = 151c = 25),底部行显示更多“本地”参数(blocksize = 51c = 5)。中间列是比邻里暗的东西(对于参数而言),右列是比邻里更亮的东西。我们看到,在更“全球”的情况下,我们得到了适当的上半场,但基本上没有“显着”的黑暗区域。看一看,在更“本地”的情况下,我们会看到一些较暗的区域,但我们不会找到完整的上半身/下半身的问题。那只是因为不同的三角形是如何排列的。

在技术方面:您需要两个cv2.adaptiveThreshold调用,一个调用使用cv2.THRESH_BINARY_INV模式来查找更暗的所有内容,另一个调用使用cv2.THRESH_BINARY模式查找更亮的所有内容。另外,您还必须为这两种不同的情况提供c-c

下面是完整的代码:

代码语言:javascript
复制
import cv2
from matplotlib import pyplot as plt
from skimage import io          # Only needed for web grabbing images

plt.figure(1, figsize=(15, 10))

img = cv2.cvtColor(io.imread('https://i.stack.imgur.com/dA1Vt.png'), cv2.COLOR_RGB2GRAY)

plt.subplot(2, 3, 1), plt.imshow(img, cmap='gray'), plt.colorbar()

# More "global" parameters
bs = 151
c = 25
img_le = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, bs, c)
img_gt = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, bs, -c)
plt.subplot(2, 3, 2), plt.imshow(img_le, cmap='gray')
plt.subplot(2, 3, 3), plt.imshow(img_gt, cmap='gray')

# More "local" parameters
bs = 51
c = 5
img_le = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, bs, c)
img_gt = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, bs, -c)
plt.subplot(2, 3, 5), plt.imshow(img_le, cmap='gray')
plt.subplot(2, 3, 6), plt.imshow(img_gt, cmap='gray')

plt.tight_layout()
plt.show()

希望这能帮上忙-不知何故!

代码语言:javascript
复制
-----------------------
System information
-----------------------
Python:      3.8.1
Matplotlib:  3.2.0rc1
OpenCV:      4.1.2
-----------------------
票数 2
EN

Stack Overflow用户

发布于 2020-01-11 01:25:06

另一种看待这个问题的方法是,在abs(均值图像) <= c中,你希望它变成白色,否则你希望它变成黑色。在Python/OpenCV/Scipy/Numpy中,我首先使用统一的51x51像素块平均滤波器(boxcar average)计算局部均匀平均(平均值)。你可以使用一些加权平均方法,如高斯平均,如果你愿意的话。然后我计算abs(平均图像)。然后我用Numpy脱粒机。注意:您也可以使用一个简单的阈值(cv2.阈值)对abs(平均图像)结果代替两个numpy阈值。

输入:

代码语言:javascript
复制
import cv2
import numpy as np
from scipy import ndimage

# read image as grayscale
# convert to floats in the range 0 to 1 so that the difference keeps negative values
img = cv2.imread('squares.png',0).astype(np.float32)/255.0

# get uniform (51x51 block) average
ave = ndimage.uniform_filter(img, size=51)

# get abs difference between ave and img and convert back to integers in the range 0 to 255
diff = 255*np.abs(ave - img)
diff = diff.astype(np.uint8)

# threshold
# Note: could also just use one simple cv2.Threshold on diff
c = 5
diff_thresh = diff.copy()
diff_thresh[ diff_thresh <= c ] = 255
diff_thresh[ diff_thresh != 255 ] = 0


# view result
cv2.imshow("img", img)
cv2.imshow("ave", ave)
cv2.imshow("diff", diff)
cv2.imshow("threshold", diff_thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()

# save result
cv2.imwrite("squares_2way_thresh.jpg", diff_thresh)

结果:

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

https://stackoverflow.com/questions/59674888

复制
相关文章

相似问题

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