我正在学习 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
中显示一个 channel 因为这不会是 GrayScale
图像(它是 Blue
channel ,因为它是 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 个 channel ,等等)。因此,第二个选项可能更适合您,因为您现在将拥有一个 Bgr
。和一个 GrayScale
.您现在仍然可以使用 Bgr
图片为您 HSV
转换等
您现在可以显示 GrayScale
像这样的图像:
PictureBox1.Image = imgGrayscale.ToBitmap()
编辑为一种颜色的阈值,而不是转换为灰度:
如果你想从图像中提取一种颜色,你不能使用 Grayscale
,即使结果将是单 channel 图像。这是因为您需要所有 channel 值来提取正确的颜色。请按照以下步骤操作:
- 找回你
Bgr
图像并将其转换为Hsv
和你一样。 - 不要将您的图像分成三个 channel ,而只是创建一个新的空图像来存储您的颜色阈值结果
- 调用
CvInvoke.InRange
函数,但将标量应用于所有三个 HSV channel 。我推荐使用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)
关于vb.net - 尝试使用 Visual Basic、OpenCV 和 EmguCV 从网络摄像头获取灰度图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43136176/