how to convert a Bgr image to YCbCr in EmguCV ?
Probably you could use the method img.Convert();
one does not simply Convert a BGR Image into YCbCr...
Image<Bgr, byte> BGR;
Image<Ycc, Byte> YCrCbFrame = BGR.Convert<Ycc, Byte>();
Related
I'm using emgu cv 3.0.0 and I would like to capture frames from a USB cam.
Unfortunately, I get an error while calling Image<Bgr, Byte> image = capture.QueryFrame();
It says, I can't convert from Emgu.CV.Mat to Emgu.CV.Image.
Try this line of code
Image<Bgr, Byte> image = capture.QueryFrame().ToImage<Bgr,Byte>();
In cv v 3.0.0 most methods use Mat for image representation.
You can try this to get the frame from the camera:
Mat frame = new Mat();
_capture.Retrieve(frame, 0);
For conversion to gray:
Mat grayFrame = new Mat();
CvInvoke.CvtColor(frame, grayFrame, ColorConversion.Bgr2Gray);
Also you can see how it works in examples here.
I have a CvVideoCamera and I'm trying to detect the blue color in each frame, and the output frames should contain only the blue objects, like here. I'm doing this in the delegate method:
- (void)processImage:(cv::Mat&)image
{
cv::Mat bgrMat;
cvtColor(image, bgrMat, CV_BGRA2BGR);
// Covert color space to HSV
cv::Mat hsvMat;
cvtColor(bgrMat, hsvMat, CV_BGR2HSV);
// Threshold the HSV image
cv::Mat blueMask;
cv::Scalar lower_blue(110, 50, 50);
cv::Scalar upper_blue(130, 255, 255);
cv::inRange(hsvMat, lower_blue, upper_blue, blueMask);
bitwise_and(bgrMat, bgrMat, image, blueMask);
}
Original image:
Result:
The blue color detection seems to be working fine, but the final result is red instead of blue. Any ideas why? Am I using the bitwise_and correctly?
[Edit]
These lines do the trick:
cv::Mat output;
image.copyTo(output, blueMask);
output.copyTo(image);
instead of:
bitwise_and(bgrMat, bgrMat, image, blueMask);
Thanks to karlphillip for the suggestion. For some reason the bgrMat gets 'altered' along the way, so I'm using the original image instead.
I think what you are trying to accomplish is to copy the pixels from the input image using a blue mask, right? Adjust your code at the end to:
cv::inRange(hsvMat, lower_blue, upper_blue, blueMask);
cv::Mat output;
bgrMat.copyTo(output, blueMask);
I am trying to script a greyscale object in a captured image as a matrix of 0 1 that represents a block of object pixels (or something like object style scaling), i can imagine the manual processing by looping the object, scaling and writing the matrix according to the grade of color,
however i'm looking for intelligent or open source tools,
.NET are preferred,
[Update, to explain in more details]
The original images are colored, however, i'm converting it into 256 greyscale, then i want to scale it into black or white only, so at the end of the day it's just a black and white picture i want convert it to zero-one matrix,
the following url contains a discussion of how to convert black-white picture to zero-one matrix using a software called imagemagick:
http://studio.imagemagick.org/discourse-server/viewtopic.php?f=1&t=18433
notice the Zero one matrix which demonstrate a dragon face image!, is there any techniques or open source tools that helping me to achieve that?
Something like the following using Emgu OpenCV for .NET would work.
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using System;
using System.Drawing;
using System.IO;
using (Image<Bgr, Byte> img = new Image<Bgr, Byte>("MyImage.jpg"))
{
Matrix<Int32> matrix = new Matrix<Int32>(img.Width, img.Height);
for (int i = 0; i<img.Height;i++)
{
for (int j = 0; j<img.Width;j++)
{
if (img.Data[i,j,2] == 255 &&
img.Data[i,j,1] == 255 &&
img.Data[i,j,0] == 255)
{
matrix.Data[i,j] = 0;
}
else
{
matrix.Data[i,j] = 1;
}
}
}
TextWriter tw = new StreamWriter("output.txt");
for (int i = 0; i<img.Height;i++)
{
for (int j = 0; j<img.Width;j++)
{
tw.Write(matrix.Data[i,j]);
}
tw.Write(tw.NewLine);
}
}
Note that the snippet above loads colour images and creates a matrix with white as 0 and 1 otherwise.
In order to load and work with grayscale images
the Image<Bgr, Byte> becomes an Image<Gray, Byte> and the comparison simplifies to just
if (img.Data[i,j,0] == 255).
Also to do the thresholding (conversion from colour to grayscale to black and white), you can use Otsu's thresholding using the cvThreshold method, using something like :
int threshold = 150;
Image<Bgr, Byte> img = new Image<Bgr, Byte>("MyImage.jpg");
Image<Gray, Single> img2 = img1.Convert<Gray, Single>();
Image<Gray, Single> img3 = new Image<Gray, Single>(img2.Width, img2.Height);
CvInvoke.cvThreshold(img2, img3, threshold, 255, THRESH.CV_THRESH_OTSU);
Other possible tools include
convert from ImageMagick and pnmoraw from netpbm, as mentioned in the URL you linked, with example snippet convert lib/dragon_face.xbm pbm: | pnmnoraw.
Using PIL (Python Image Library) to iterate through image data and the Python IO functions to write the output data
Using System.Drawing.Bitmap specifically the GetPixel method to iterate through the image data, and C# IO functions to write the output data.
In the canny edge detector the input required is a gray image...
Is there any direct color edge detector function in open-cv ? Or is it same if i convert to gray scale and use canny ?
I ask this because I need to see the edge detection map of a color image for further processing... That is I need to calculate all the horizontal and vertical line segments in a color image... Thus i was thinking of first calculating all edges of the image ...
Can someone help me how i should progress ...
Matthias Odisio is correct thanks you even corrected me and you've explained the reason very well. The solution then would be to perform edge detection on each colour spectrum:
Image<Bgr, Byte> img = new Image<Bgr, Byte>(open.FileName);
Image<Bgr, Byte> Result = new Image<Bgr, Byte>(img.Size);
Result[0] = img[0].Canny(new Gray(10), new Gray(60));
Result[1] = img[0].Canny(new Gray(10), new Gray(60));
Result[2] = img[0].Canny(new Gray(10), new Gray(60));
Hope this helps,
Chris
So, I have this image of a face:
http://i.stack.imgur.com/gsZnh.jpg
and I need to be able to determine the most dominate/prominent RGB and The YCrCB value from it using Emgu CV. Thank you for the help.
You should first get the histogram of every color channel. Then you can use minmax function to get the most dominant color.
The code I'm posting is for an HSV image, you can change channel names for your color space.
Image<Gray, Byte>[] channels = hsv1.Split();
Image<Gray, Byte> ImgHue = channels[0];
Image<Gray, Byte> ImgSat = channels[1];
Image<Gray, Byte> ImgVal = channels[2];
DenseHistogram histo1 = new DenseHistogram(255, new RangeF(0, 255));
histo1.Calculate<byte>(new Image<Gray, byte>[] { ImgHue }, true, null);
float minV, maxV;
int[] minL;
int[] maxL;
histo1.MinMax(out minV, out maxV, out minL, out maxL);
string mystr = Convert.ToString(maxL[0]);
label1.Text = "Hue= " + mystr;
You can do the same thing for Saturation and Value channels too.
You can use histogram to find the distribution of colors and choose the highest value as the dominant color. Don't know about related functions in Emgu CV though for now. Good Luck