尝试使用 Visual Basic、OpenCV 和 EmguCV 从网络摄像头获取灰度图像

Trying to obtain gray images from webcam using Visual Basic, OpenCV and EmguCV

我正在学习 OpenCV 和 EmguCV。我通过尝试从我的网络摄像头获取图像而获得成功,现在我正在尝试获取灰度图像。

实现这个之后,我的目的是识别和跟踪颜色,所以我试图以 HVS 格式获取图像以过滤图像以仅显示我在白色中寻找的颜色,以及图像的其余部分黑色(希望你能理解我的解释)

现在,我只想使用以下代码从我的网络摄像头获取灰度图像:

Imports Emgu.CV

Imports Emgu.CV.Util

Imports Emgu.CV.Structure

Imports System.Drawing

Public Class Form1

Dim capturez As Capture = New Capture
Dim radius As Decimal = 50.0F
Dim x As Decimal
Dim y As Decimal

Private Sub Timer1_Tick() Handles Timer1.Tick

    'Define x and y to determinate the position of the circle in the PictureBox
    x = PictureBox1.Width / 2 - radius
    y = PictureBox1.Height / 2 - radius

    'PointF type defines the X and Y position of the future circle in the PictureBox
    Dim point1 As New PointF(x, y)
    Dim circle As CircleF = New CircleF(point1, radius)
    Dim img As Image(Of Bgr, Byte) = capturez.QueryFrame()

    'Convert camera capture from BGR to HVS
    Dim hvs_frame As Image(Of Hsv, Byte) = img.Convert(Of Hsv, Byte)()

    'Obtain the three channels that compose the HVS image (hue, saturation and value)
    Dim channels As Image(Of Gray, Byte)() = hvs_frame.Split()


    'Remove all pixels from the hue channel that are not in the range [40, 60]
    CvInvoke.cvInRangeS(channels(0), New Gray(200).MCvScalar, New Gray(255).MCvScalar, channels(0))

    'Display converted frame
    PictureBox1.Image = channels(0).ToBitmap()

    'When commenting the .CopyBlank() property, the back color of the PictureBox remains transparent
    'When uncomment this, the back color of the PictureBox becomes black
    Dim imageCircle As Image(Of Bgr, Byte) = img '.CopyBlank()
    imageCircle.Draw(circle, New Bgr(Color.Brown), 2)
    PictureBox1.Image = imageCircle.ToBitmap()
End Sub

使用此代码,我只能获取 BGR 中的图像,我不知道为什么,因为我在 'PictureBox1.Image' 中指定我想要该灰度图像。

请帮帮我=(

我正在使用 OpenCV 2.4.9 和 EmguCV 2.4.0 ... 如果需要的话

非常感谢!

目前您正在拍摄彩色图像 (BGR),因此您不能只在 Picturebox 中显示一个通道,因为这不是 GrayScale 图像(这是 Blue 频道,因为它是 BGR 图片)。您可以通过两种方式解决此问题。

第一个选项是在 GrayScale 中专门从您的相机中检索帧。你可以这样实现:

Dim imgGrayscale As Image(Of Gray, Byte) = capturez.RetrieveGrayFrame()

另一种选择是在从网络摄像头捕获的图像中检索图像后将其转换为 GrayScale。你可以这样实现:

Dim img As Image(Of Bgr, Byte) = capturez.QueryFrame()
Dim imgGrayscale As Image(Of Gray, Byte) = img.Convert(Of Gray, Byte)()

请注意,从这一刻起,您将使用 GrayScale 图像,这将影响您的其余代码(即,您将不再有 3 个通道,等等)。因此,第二个选项可能更适合您,因为您现在将有一个 Bgr 和一个 GrayScale。您现在仍然可以使用 Bgr 图像进行 HSV 转换等

您现在可以像这样显示 GrayScale 图像:

PictureBox1.Image = imgGrayscale.ToBitmap()

编辑为一种颜色的阈值,而不是转换为灰度:

如果您想从图像中提取一种颜色,您不能使用 Grayscale,即使结果将是单通道图像。这是因为您需要所有通道值来提取正确的颜色。按照以下步骤操作:

  • 检索您的 Bgr 图像并将其转换为 Hsv
  • 不要将你的图像分成三个通道,而只是创建一个新的空图像来存储你的颜色阈值结果
  • 调用 CvInvoke.InRange 函数,但将标量应用于所有三个 HSV 通道。我建议使用 InRange 而不是 InRangeS 因为后者来自 OpenCV 1.X.
  • InRange 函数的工作原理如下:MCvScalars 表示 HSV 范围内的颜色值范围。它检查每个像素并比较它是否在您指定的标量值范围内。如果是,它将获得 255 像素值(白色),否则将获得 0(黑色)。这会给你一个阈值图像。
  • 如果你想提取更多的颜色范围,你可以添加更多的CvInvoke.Inrange方法,稍后用CvInvoke.Add函数添加不同的结果。
  • 尝试使用您设置的 MCvScalar 边界来提取颜色,如果它们没有给您正确的结果。此外,如果您想获得不同的颜色,请修改边界。您可以使用颜色选择器检索特定颜色的 HSV 值。即使是 MS Paint 中的颜色选择器也会为您提供 Hue/Sat/Lum 值,但您必须转换这些值(它们的比例不同,MS Paint 0-239OpenCV 0-179)。因此,通过将级别乘以 180/240.
  • 来转换它们

你会得到这样的东西:

` Get the webcam frame
Dim webcam_image As Mat
webcam_image = capturez.QueryFrame()

` Get an empty HSV image and threshold image
Dim HSV_img As New Mat(webcam_image.Size, DepthType.Cv8U, 3)
Dim threshold_img As New Mat(webcam_image.Size, DepthType.Cv8U, 1)

' Convert camera capture from BGR to HVS
CvInvoke.CvtColor(webcam_image, HSV_img, ColorConversion.Bgr2Hsv)

` Threshold the yellow colors only (please adopt the scalar values to whatever values suit your needs)
CvInvoke.InRange(HSV_img, New ScalarArray(New MCvScalar(20, 100, 100)), New ScalarArray(New MCvScalar(30, 255, 255)), threshold_img)