使用Emgu识别图像中的黄点 [英] Identify Yellow spot's in Images using Emgu
本文介绍了使用Emgu识别图像中的黄点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
如何使用EMGUCV识别图像中的黄斑
How shall i identify yellow spot in Images using EMGUCV
推荐答案
EMGUCV包含OpenCV库API中的大部分功能,因此大多数OpenCV示例(在C / C ++中)都是也适用于EmguCV。 Android端口也有很多样本(在Java / C ++中)。有这么多样本(例如这一个 http:// opencv-srf.blogspot.com.es/2010/09/object-detection-using-color-seperation.html [ ^ ])我认为这可能会更有助于告诉你部分理由背后的原因代码:
从一个图像中检测颜色区域可以简化为以下步骤:
1)将捕获的图像颜色空间转换为HSV,因为这种类型的处理更方便。参见cvtColor()
函数。
2)你可以选择pyrDown()
你的形象使处理更快。
3)过滤图像以减少噪音,你可以使用高斯滤波器。请参阅函数cvSmooth()
,过滤器类型为CV _GAUSSIAN
。
4)有趣的部分,现在你只需要使用两个极限高低来压制你的图像。看一下函数cvInRangeS()
。
在这个处理之后,你将有一个二进制图像,而不是null,以与cvInRangeS()
中使用的颜色cryteria匹配的像素为单位。后续步骤取决于您的应用程序,可能涉及findContours()
或用于检测场景中对象的任何其他原语。
EMGUCV wraps most functions from the OpenCV library API so most OpenCV examples (in C/C++) are also valid for EmguCV. There're lots of samples also for the Android port (in Java/C++). With so many samples out there (e.g. this one http://opencv-srf.blogspot.com.es/2010/09/object-detection-using-color-seperation.html[^]) I think it could be of more help telling you part of the rationale behind the code:
Detecting color regions from one image can be simplified to the following steps:
1) Convert your captured image color space to HSV as it is more convenient for this type of processing. SeecvtColor()
function.
2) You may optionalypyrDown()
your image to make processing faster.
3) Filter the image for reducing noise, you may use the gaussian filter. See functioncvSmooth()
with filter type CV_GAUSSIAN
.
4) The funny part, now you just have to thresshold your image using two limits High and Low. Take a look at functioncvInRangeS()
.
After this processing you'll have one binary image, not null in pixels that match the color cryteria used incvInRangeS()
. Next steps depend on your application and could involvefindContours()
or whatever other primitive used to detect objects in the scene.
(发布为解决方案,因为一条评论太长了)
来自你的问题标签我假设您正在使用C#。我已经尝试过这段代码(在评论之后),它对我有用。它会有错误,值肯定需要修剪。它使用包装类并避免使用native / interop调用。
创建一个表单并放置两个名为'captureImageBox'和'的Emgu.CV.UI.ImageBox对象processedImageBox。还可以放置一个名为m_btnCapture的按钮。将下面的代码添加到表单的代码文件中。
代码使用第二个网络摄像头(用于在我的电脑中使用嵌入式网络摄像头以外),一个图像框显示原始图像(过滤)帧和另一个二进制处理帧。黑色是场景背景和白色检测(阈值)颜色区域。
当您单击按钮时,它会启动/停止捕获。点击拍摄的图像选择一种颜色。
希望它适合你。
Hi,
(posted as solution as it is too long for one comment)
From your question tags I suppose you're using C#. I've tried this code (after the comment) and it works for me. It will have bugs and the values should surely require trimming. It uses the wrapping classes and avoids using the native/interop calls.
Create one form and place two Emgu.CV.UI.ImageBox objects named 'captureImageBox' and 'processedImageBox'. Also place one button named 'm_btnCapture'. Add the code below to the form's code file.
The codes uses the second webcam (for using other than the embedded one in my pc), one imagebox shows the original (filtered) frame and the other the binary processed frame. Black is scene background and white detected (thresholded) color regions.
When you click the button it starts/stops captures. Click on the captured image to select one color.
Hope it works for you.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.Structure;
namespace ColorDet
{
public partial class Form1 : Form
{
private Capture _capture;
private bool _captureInProgress;
private Rectangle m_Rect;
private Point m_ClickPoint;
private Hsv m_TargetColor;
private bool m_TrackColor;
private Hsv m_Lower;
private Hsv m_Higher;
public Form1()
{
m_Rect = Rectangle.Empty;
m_ClickPoint = Point.Empty;
m_TrackColor = false;
InitializeComponent();
}
private void ProcessFrame(object sender, EventArgs arg)
{
Image<Bgr, Byte> frame = _capture.QueryFrame();
frame = frame.SmoothGaussian(3, 3, 1, 1);
if (!m_ClickPoint.Equals(Point.Empty))
{
Rectangle Rect = new Rectangle(m_ClickPoint.X - 5, m_ClickPoint.Y - 5, 10, 10);
if (Rect.X < 0)
Rect.X = 0;
if (Rect.Y < 0)
Rect.Y = 0;
using (Image<Bgr, Byte> TouchRegion = frame.GetSubRect(Rect))
{
using (Image<Hsv, Byte> TouchRegionHsv = TouchRegion.Convert<Hsv, byte>())
{
int Points = TouchRegion.Width*TouchRegion.Height;
m_TargetColor = TouchRegionHsv.GetAverage();
Bgr Colr = Convert(m_TargetColor);
m_Lower = new Hsv(m_TargetColor.Hue - 30, m_TargetColor.Satuation - 30, m_TargetColor.Value - 30);
m_Higher = new Hsv(m_TargetColor.Hue + 30, m_TargetColor.Satuation + 30, m_TargetColor.Value + 30);
panel2.BackColor = Color.FromArgb((int)Colr.Red, (int)Colr.Green, (int)Colr.Blue);
frame.Draw(Rect, new Bgr(Color.Red), 1);
m_TrackColor = true;
}
}
m_ClickPoint = Point.Empty;
}
if (m_TrackColor)
{
Image<Hsv, Byte> HsvFrame = frame.Convert<Hsv, byte>();
HsvFrame = HsvFrame.SmoothGaussian(5, 5, 0.1, 0.1);
Image<Gray, byte> InRageFrame = HsvFrame.InRange(m_Lower, m_Higher);
processedImageBox.Image = InRageFrame;
}
captureImageBox.Image = frame;
}
const float FLOAT_TO_BYTE = 255.0f;
const float BYTE_TO_FLOAT = 1.0f / FLOAT_TO_BYTE;
private Bgr Convert(Hsv hsv)
{
int H = (int)hsv.Hue;
int S = (int)hsv.Satuation;
int V = (int)hsv.Value;
// HSV to RGB color conversion in OpenCV
int bH = H; // H component
int bS = S; // S component
int bV = V; // V component
float fH, fS, fV;
float fR, fG, fB;
// Convert from 8-bit integers to floats
fH = (float)bH * BYTE_TO_FLOAT;
fS = (float)bS * BYTE_TO_FLOAT;
fV = (float)bV * BYTE_TO_FLOAT;
// Convert from HSV to RGB, using float ranges 0.0 to 1.0
int iI;
float fI, fF, p, q, t;
if (bS == 0)
{
// achromatic (grey)
fR = fG = fB = fV;
}
else
{
// If Hue == 1.0, then wrap it around the circle to 0.0
if (fH >= 1.0f)
fH = 0.0f;
fH *= (float)6.0; // sector 0 to 5
fI = (float)Math.Floor(fH); // integer part of h (0,1,2,3,4,5 or 6)
iI = (int)fH; // " " " "
fF = fH - fI; // factorial part of h (0 to 1)
p = fV * (1.0f - fS);
q = fV * (1.0f - fS * fF);
t = fV * (1.0f - fS * (1.0f - fF));
switch (iI)
{
case 0:
fR = fV;
fG = t;
fB = p;
break;
case 1:
fR = q;
fG = fV;
fB = p;
break;
case 2:
fR = p;
fG = fV;
fB = t;
break;
case 3:
fR = p;
fG = q;
fB = fV;
break;
case 4:
fR = t;
fG = p;
fB = fV;
break;
default: // case 5 (or 6):
fR = fV;
fG = p;
fB = q;
break;
}
}
// Convert from floats to 8-bit integers
int bR = (int)(fR * FLOAT_TO_BYTE);
int bG = (int)(fG * FLOAT_TO_BYTE);
int bB = (int)(fB * FLOAT_TO_BYTE);
// Clip the values to make sure it fits within the 8bits.
if (bR > 255)
bR = 255;
if (bR < 0)
bR = 0;
if (bG > 255)
bG = 255;
if (bG < 0)
bG = 0;
if (bB > 255)
bB = 255;
if (bB < 0)
bB = 0;
// Set the RGB cvScalar with G B R, you can use this values as you want too..
return new Bgr(bB, bG, bR); // R component
}
private void m_btnCapture_Click(object sender, EventArgs e)
{
if (_capture == null)
{
try
{
_capture = new Capture(1);
}
catch (NullReferenceException excpt)
{
MessageBox.Show(excpt.Message);
}
}
if (_capture != null)
{
_captureInProgress = !_captureInProgress;
if (!_captureInProgress)
{ //stop the capture
m_btnCapture.Text = "Capture";
Application.Idle -= ProcessFrame;
}
else
{
//start the capture
m_btnCapture.Text = "Stop";
Application.Idle += ProcessFrame;
}
}
}
private void ReleaseData()
{
if (_capture != null)
{
_capture.Dispose();
_capture = null;
}
}
private void captureImageBox_MouseClick(object sender, MouseEventArgs e)
{
//e.X;
m_ClickPoint = new Point(e.X, e.Y);
}
}
}
这篇关于使用Emgu识别图像中的黄点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文