尝试使用 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-239
和 OpenCV 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)
我正在学习 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-239
和OpenCV 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)