我需要从一个区域检测蠕虫的形状。
我尝试使用许多功能从带阈值的固定图像中提取形状,但没有成功。 我注意到,我可以使用他的身体反射的光线看到蠕虫的形状,这种反射或多或少像一个C字母的小弧,具有许多方向和大小。 我检测到了这种反射,并用圆圈将其包围。
IMG1:如您所见,这是唯一具有弧形圆的区域
我试图创建一个模板库,以使用this article来识别所有'C'形式的相似性,并且效果很好,但是由于我的圈子组不够精确,轮廓analisys并不可靠。>
然后我考虑将一个范围内的所有斜切圆合并以创建更易读的C形,但是我不知道该怎么做。
另一种选择是验证每个圆是否在一定范围内有另一个圆,验证是否存在3个或更多,并验证通过所有圆心的虚拟线的坐标是否会形成圆弧。情况下我可能有一个C。此外,我可以继续在找到的C圆周上向左和向右找到圆,以验证是否存在更多要整合为C形的圆。 我不确定最好的方法是什么,目前我很乐意验证是否有任何圆圈在附近,或者如何“融化”附近的圆圈以创建更整洁的身材。
我在EmguCv
C#
工作,但也接受phython
的建议。 :)。 (请不要c++
)
我的英语致歉。
有关信息,这是绘制圆的功能。
// ************************************************************
private void BlobFind(Image<Bgr, byte> img)
{
double dp = 0;
double distMin = 0;
double cannyThreshold = 0;
double circleAccumulatorThreshold = 0;
int circleRadiusMin = 0;
int circleRadiusMax = 0;
// pen for circles
Pen penYellow = new Pen(new SolidBrush(Color.Yellow), 1);
Pen penRed = new Pen(new SolidBrush(Color.Red), 3);
Pen penGreen = new Pen(new SolidBrush(Color.Green), 3);
Pen penWhite = new Pen(new SolidBrush(Color.White), 3);
// *******************
// circles coordinates list
List<float> m_ListaCerchi = new List<float>();
// *******************
dp = (float)TbCannyAccumulator.Value / 10;
distMin = TbCannyThresh.Value;
cannyThreshold = tbWCCannyMin.Value;
circleAccumulatorThreshold = tbWCCannyMax.Value;
circleRadiusMin = TbCannyRadiusMin.Value;
circleRadiusMax = TbCannyRadiusMax.Value;
PictureBox pic = new PictureBox();
//Convert the image to grayscale and filter out the noise
UMat uimage = new UMat();
uimage = img.ToUMat();
// gray conversion
CvInvoke.CvtColor(uimage, uimage, ColorConversion.Bgr2Gray);
// circle detection
CircleF[] circles = CvInvoke.HoughCircles(uimage, HoughType.Gradient, dp, distMin, cannyThreshold, circleAccumulatorThreshold, circleRadiusMin, circleRadiusMax);
if (circles.Length == 0) return;
// circles draw
Image<Bgr, Byte> circleImage = img.CopyBlank();
Graphics g = pictureBox1.CreateGraphics();
// circles coordinates
m_CirclesList.Clear();
int circlesCounter = 0;
// found circles loop
m_FlgEndAnalisis = false;
foreach (CircleF circle in circles)
{
float trimRadius = float.Parse(nudtrimRadius.Value.ToString());
// coordinate circle
float radius = circle.Radius;
radius += trimRadius;
float x = circle.Center.X - radius;
float y = circle.Center.Y - radius;
float width = 2 * radius;
float height = 2 * radius;
bool FlgCompleteCircle = true;
// verify if outbound circle
if (circle.Center.X + radius > pictureBox1.Width ||
circle.Center.X - radius < 0 ||
circle.Center.Y + radius > pictureBox1.Height ||
circle.Center.Y - radius < 0)
{
FlgCompleteCircle = false;
}
if (FlgCompleteCircle == false) // outbound circle
{
x = circle.Center.X - radius;
y = circle.Center.Y - radius;
width = 2 * radius;
height = 2 * radius;
// draw outbound circle
g.DrawEllipse(penRed, x, y, width, height);
}
// ***********************
int X0 = (int)x;
int Y0 = (int)y;
int X1 = X0 + (int)radius * 2;
int Y1 = Y0 + (int)radius * 2;
// area to copy
int wid = Math.Abs(X0 - X1);
int hgt = Math.Abs(Y0 - Y1);
if ((wid < 1) || (hgt < 1)) return;
Bitmap area = new Bitmap(wid, hgt);
using (Graphics gr = Graphics.FromImage(area))
{
Rectangle source_rectangle = new Rectangle(Math.Min(X0, X1), Math.Min(Y0, Y1), wid, hgt);
Rectangle dest_rectangle = new Rectangle(0, 0, wid, hgt);
gr.DrawImage(pictureBox1.Image, dest_rectangle, source_rectangle, GraphicsUnit.Pixel);
}
// OK
Image<Gray, Byte> myImage = new Image<Gray, Byte>(area);
Gray m_TargetColor;
m_TargetColor = myImage.GetAverage();
// *************************
if (FlgCompleteCircle == true)
{
// if circle complete save coordinates
circlesCounter++;
float[] Circle_coord = { circlesCounter, x, y, radius }; // radius is always the same
m_CirclesList.AddRange(Circle_coord);
// draw circle number
using (Font myFont = new Font("Arial", 12))
{
g.DrawString(circlesCounter.ToString(), myFont, Brushes.White, new Point((int)x + (int)radius - 10, (int)y + (int)radius - 20));
}
// draw main circle
g.DrawEllipse(penWhite, x, y, width, height);
}
}
m_FlgEndAnalisis = true;
}