Reputation: 429
I am learning about OpenCV and EmguCV. I succeed by trying to obtain images from my webcam and now I'm trying to obtain that images in a gray scale.
My purpose after achieve this, is to recognize and track colors, so im trying to obtain the image in a HVS format to filter the image to display only the color Im looking for in white, and the rest of the image in black (I hope you understand my explanation)
Now, I only want to obtain the image from my webcam in that gray scale using the following code:
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
With this code, I am only obtaining the image in BGR, and I don't know why, because I am specifying in the 'PictureBox1.Image' that I want the image in that gray scale.
Please help me =(
I'm using OpenCV 2.4.9 and EmguCV 2.4.0 ... if needed
Thanks a lot!
Upvotes: 1
Views: 2092
Reputation: 1396
Currently you are capturing the image in color (BGR
) so you can't just show one channel in your Picturebox
as this won't be a GrayScale
image (it's the Blue
channel, since it's a BGR
image). You can solve this in two ways.
The first option is to specifically retrieve the frame from your camera in GrayScale
. You can achieve this like this:
Dim imgGrayscale As Image(Of Gray, Byte) = capturez.RetrieveGrayFrame()
The other option is to convert your image to GrayScale
after you've retrieved it from the webcam capture. You can achieve this like this:
Dim img As Image(Of Bgr, Byte) = capturez.QueryFrame()
Dim imgGrayscale As Image(Of Gray, Byte) = img.Convert(Of Gray, Byte)()
Note that from this moment you will be working with a GrayScale
image, which will impact the rest of your code (i.e. you will not have 3 channels anymore, etc.). Therefore the second option may be more suitable for you, as you will now have a Bgr
and a GrayScale
. You can now still use the Bgr
image for your HSV
conversion etc.
You can now show the GrayScale
image like this:
PictureBox1.Image = imgGrayscale.ToBitmap()
EDIT to threshold one color, instead of converting to grayscale:
If you want to extract one color from the image, you can't use Grayscale
, even though the result will be a one channel image. This is because you need all channel values to extract the right color. Follow the following steps:
Bgr
image and convert it to Hsv
as you did.CvInvoke.InRange
function, but apply the scalar to all three HSV channels. I recommend the use of InRange
and not InRangeS
as the latter is from OpenCV 1.X.InRange
function works as follows: the MCvScalars
represent the bounds of your color values in HSV
range. It checks each pixel and compares if it is within the scalar values you stated. If it is, it will get a 255
pixel value (white) and otherwise 0
(black). That will give you a thresholded image.CvInvoke.Inrange
methods and add the different results with a CvInvoke.Add
function later.MCvScalar
bounds you set to extract your color if they don't give you the right result. Also, if you want to obtain a different color, modify the bounds. You can use color pickers to retrieve the HSV
values of certain color. Even a color picker in MS Paint will give you the Hue/Sat/Lum
values, but you have to convert these (they are on a different scale, MS Paint 0-239
and OpenCV 0-179
). So convert them by multiplying the levels by 180/240
.You will get something like this:
` 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)
Upvotes: 2