using System;
using System.Collections;
using System.Collections.Generic;
using Emgu.CV;
using Emgu.CV.Structure;
using System.Drawing;
namespace BulbsLightMatcher
{
//@todo: replace all this shitty mess with getters/setters
/**
* Data instance parent class
*/
abstract public class DataInstance
{
protected MCvHuMoments moments;
protected uint colorGroup = 0;
protected Image<Bgr, Int32> sourceImage;
protected Image<Gray, Byte> cannyEdges;
/**
* void dataInstance( string file )
*
* @param string file - contains full path to image.
*/
public DataInstance(string file)
{
sourceImage = new Image<Bgr, Int32>(file);
prepareImage();
Image<Gray, Byte> gray = sourceImage.Convert<Gray, Byte>();//.PyrDown().PyrUp();
Gray cannyThreshold = new Gray(90);
Gray cannyThresholdLinking = new Gray(150);
cannyEdges = gray.Canny(cannyThreshold, cannyThresholdLinking);
Contour<Point> contours;
//@todo: use namespace for this
MemStorage storage = new MemStorage();
{ //allocate storage for contour approximation
contours = cannyEdges.FindContours(
Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_LINK_RUNS,
Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_CCOMP,
storage);
Contour<Point> contoursTop = contours;
double p;
Point cornerTop, cornerBottom, cornerLeft, cornerRight;
cornerTop = new Point(0, sourceImage.Height);
cornerBottom = new Point(0, 0);
cornerLeft = new Point(sourceImage.Width, 0);
cornerRight = new Point(0, 0);
while (contours.HNext != null)
{
p = contours.Perimeter;
if (p > 100)
{
Rectangle tmp = contours.BoundingRectangle;
//Retriving padding
if (sourceImage.Height - tmp.Bottom > 10 && tmp.Top > 10 && tmp.Left > 10 && sourceImage.Width - tmp.Right > 10)
{
Point[] data = contours.ToArray();
foreach (Point point in data)
{
if (point.Y < cornerTop.Y)
cornerTop = point;
else if (point.Y > cornerBottom.Y)
cornerBottom = point;
if (point.X > cornerRight.X)
cornerRight = point;
else if (cornerLeft.X > point.X)
cornerLeft = point;
}
sourceImage.Draw(tmp, new Bgr(0, 255, 125), 1);
sourceImage.Draw(contours, new Bgr(0, 0, 255), 1);
}
}
contours = contours.HNext;
}
LineSegment2D yOrd = new LineSegment2D(cornerTop, cornerBottom);
LineSegment2D xOrd = new LineSegment2D(cornerLeft, cornerRight);
sourceImage.Draw(xOrd, new Bgr(255, 0, 0), 2);
sourceImage.Draw(yOrd, new Bgr(255, 0, 0), 2);
contours = contoursTop;
moments = contoursTop.GetMoments().GetHuMoment();
cannyEdges = null;
sourceImage = null;
}
}
/**
* void dataInstance( MCvHuMoments m, uint color )
*
* Constructor. May be used when all data allready computed.
*/
public DataInstance(MCvHuMoments m, uint color)
{
moments = m;
colorGroup = color;
}
/**
* double[] GetMoments()
*
* @return an array of Hu moments.
*/
public double[] GetMoments()
{
double[] data = new double[7];
data[0] = moments.hu1;
data[1] = moments.hu2;
data[2] = moments.hu3;
data[3] = moments.hu4;
data[4] = moments.hu5;
data[5] = moments.hu6;
data[6] = moments.hu7;
return data;
}
/**
* double Compare()
*
* Compares Hu Moments. Copy-paste from openCV source.
*
* @return some coef.
*/
public double Compare(DataInstance item, Emgu.CV.CvEnum.CONTOURS_MATCH_TYPE method)
{
int i, sma, smb;
double[] ma, mb;
double result = 0, mmm;
double eps = Double.Parse("1.e-5");
ma = GetMoments();
mb = item.GetMoments();
switch ((int)method)
{
case 1:
{
for (i = 0; i < 7; i++)
{
double ama = Math.Abs(ma[i]);
double amb = Math.Abs(mb[i]);
if (ma[i] > 0)
sma = 1;
else if (ma[i] < 0)
sma = -1;
else
sma = 0;
if (mb[i] > 0)
smb = 1;
else if (mb[i] < 0)
smb = -1;
else
smb = 0;
if (ama > eps && amb > eps)
{
ama = 1.0 / (sma * Math.Log10(ama));
amb = 1.0 / (smb * Math.Log10(amb));
result += Math.Abs(-ama + amb);
}
}
break;
}
case 2:
{
for (i = 0; i < 7; i++)
{
double ama = Math.Abs(ma[i]);
double amb = Math.Abs(mb[i]);
if (ma[i] > 0)
sma = 1;
else if (ma[i] < 0)
sma = -1;
else
sma = 0;
if (mb[i] > 0)
smb = 1;
else if (mb[i] < 0)
smb = -1;
else
smb = 0;
if (ama > eps && amb > eps)
{
ama = sma * Math.Log10(ama);
amb = smb * Math.Log10(amb);
result += Math.Abs(-ama + amb);
}
}
break;
}
case 3:
{
for (i = 0; i < 7; i++)
{
double ama = Math.Abs(ma[i]);
double amb = Math.Abs(mb[i]);
if (ma[i] > 0)
sma = 1;
else if (ma[i] < 0)
sma = -1;
else
sma = 0;
if (mb[i] > 0)
smb = 1;
else if (mb[i] < 0)
smb = -1;
else
smb = 0;
if (ama > eps && amb > eps)
{
ama = sma * Math.Log10(ama);
amb = smb * Math.Log10(amb);
mmm = Math.Abs((ama - amb) / ama);
if (result < mmm)
result = mmm;
}
}
break;
}
}
return result;
}
/**
* void prepareImage()
*
* Preapares image for matching
*/
public virtual void prepareImage()
{
}
/**
* Bitmap GetBitmap()
*
* This method is only for testing
*
* @return Image with overlay contours.
*/
/* public Bitmap GetBitmap()
{
return sourceImage.ToBitmap();
}*/
}
}