有没有办法使阈值图像检测对象本身而不是轮廓? - OpenCV

发布于 2025-02-10 00:01:03 字数 930 浏览 4 评论 0原文

我有以下图像,并试图使阈值映像成为填充对象(斑点),但看来阈值图像只是轮廓。有没有更好的方法使阈值图像显示整个对象而不是轮廓?

“灰度图像”

​,但出于其他目的,最好将面具成为完整的斑点。也就是说,拥有更好的面具将使我在以后的步骤中更加灵活。

(当前代码的重要部分):

# convert original image (image 1) to grayscale 
gray_frame = cv2.cvtColor(curFrame, cv2.COLOR_BGR2GRAY)
  
# apply Gaussian blur to reduce noise (image 2)
gray_frame = cv2.GaussianBlur(gray_frame, (3, 3), 0)
  
# image 3
threshold = cv2.adaptiveThreshold(gray_frame, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 5, 3)

I have the following image and am trying to get the threshold image to be the filled-in objects (the blobs), but it appears that the threshold image is just the outline. Is there a better way to make the thresh image show the entire object rather than the outline?

original imagegrayscale imagethreshold image

Currently, I'm using the mask I have and taking the outermost contours from the image and filling them in (using cv2.findContours and cv2.drawContours), but for other purposes, it would be best to make the mask be the full blobs. Namely, having a better mask would allow me more flexibility in later steps.

(Important parts of) current code:

# convert original image (image 1) to grayscale 
gray_frame = cv2.cvtColor(curFrame, cv2.COLOR_BGR2GRAY)
  
# apply Gaussian blur to reduce noise (image 2)
gray_frame = cv2.GaussianBlur(gray_frame, (3, 3), 0)
  
# image 3
threshold = cv2.adaptiveThreshold(gray_frame, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 5, 3)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

三生路 2025-02-17 00:01:03

介绍:

您选择了错误的OPENCV功能来完成工作。自适应阈值将图像分为预定义尺寸的块。阈值操作在每个单个块中进行,彼此独立。

您需要的是OpenCV的全局阈值函数:cv2.threshold,它允许您为整个图像设置一个阈值。

通过此文档页面以获取更多详细信息。

为什么自适应阈值不起作用?

如前所述,阈值是根据图像的预定义区域内的像素强度计算得出的。这是针对每个区域独立完成的。

让我们在下面拍摄示例图像:

”在此处输入映像说明“

用内核尺寸5和常数3执行自适应阈值(来自代码)给出以下内容:

adapt_thresh = cv2.adaptiveThreshold(binary_img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 5, 3)

​查看此插图:

“在此处输入图像描述”

在带有2种灰色阴影的图像上使用了一些大小的正方形内核。以上表示3个不同的内核位置的3种不同方案。当内核位于两个阴影区域中的任何一个时,阈值基于内核区域内的所有像素强度 ,因此结果在结果中没有反映。在第三种情况下,当内核沿2个区域的边缘时,阈值是基于该区域中每个像素的高斯重量获得的阈值。高于阈值的像素为白色(255),下面的像素为黑色(0)。

为了使您继续使用自适应阈值,您需要使用与图像中斑点大小相似的内核大小。常数“ C”也是您必须调整的参数。

什么将有效?

以下代码显示全局阈值函数:

img =cv2.imread('blobs.png')
blur = cv2.GaussianBlur(img, (3, 3), 0)

# convert to LAB color space
lab = cv2.cvtColor(blur, cv2.COLOR_BGR2LAB)

# get luminance channel
l_component = lab[:, :, 0]

“在此处输入图像说明”

上图中的斑点看起来比其他区域更暗。在下面选择合适的阈值值使我们可以分割:

# setting threshold level at 125
ret, thresh = cv2.threshold(l_component, 125, 255, cv2.THRESH_BINARY)

Intro:

You chose the wrong OpenCV function to do your job. Adaptive threshold divides the image into blocks of predefined sizes. Threshold operation is carried out in each of these individual blocks, independent of each other.

What you need is OpenCV's global threshold function: cv2.threshold, which allows you to set a single threshold value for the entire image.

Go through this documentation page for more details.

Why won't Adaptive Threshold work?

As mentioned earlier, threshold is calculated based on pixel intensities within a predefined region of the image. This is done for each region, independently.

Let's take a sample image below:

enter image description here

Performing adaptive threshold (from your code) with kernel size 5 and constant 3 gives the following:

adapt_thresh = cv2.adaptiveThreshold(binary_img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 5, 3)

enter image description here

To understand what happens here, have a look at this illustration:

enter image description here

A square kernel of some size is used (black) on an image with 2 shades of gray. The above represents 3 different scenarios for 3 different kernel positions. When the kernel is positioned on either of the 2 shaded regions, the threshold value is based on all the pixel intensities within the kernel region which are all the same, hence no change is reflected in the result. In the third scenario, when the kernel is along the edge of the 2 regions, threshold value is obtained based on Gaussian weight for each pixel in that region. Pixels higher than the threshold are made white (255), and those below are made black (0).

In order for you to continue working with adaptive threshold, you need to use a kernel size that closely resemble the size of the blobs in the image. The constant 'C' is also a parameter you would have to tune.

What would work?

The following code shows global threshold function:

img =cv2.imread('blobs.png')
blur = cv2.GaussianBlur(img, (3, 3), 0)

# convert to LAB color space
lab = cv2.cvtColor(blur, cv2.COLOR_BGR2LAB)

# get luminance channel
l_component = lab[:, :, 0]

enter image description here

The blobs in the above image appear darker than other regions. Choosing a suitable threshold value below allows us to segment it:

# setting threshold level at 125
ret, thresh = cv2.threshold(l_component, 125, 255, cv2.THRESH_BINARY)

enter image description here

Attempts:

You can also try:

  • Changing the kernel size used in blurring operation
  • Use the grayscale image as input
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文