/// <summary> /// build template List from a Gray image /// </summary> /// <param name="image">input image</param> /// <param name="buildXMLTemplateFile">true to build a xml file with current templates</param> /// <param name="angles">the number of angles, default to 360</param> /// <param name="sizes">number of sizes, default to 1</param> /// <param name="minRatio">The ratio of smallest size to original, default to 0.6</param> /// <param name="maxFeaturesPerLevel">the array of maximum features per pyrimid level, default to 200 in DEFAULT_MAX_FEATURES_PER_LEVEL from ImageTemplatePyramid.cs:56, /// increase to increase the precision in expense of detection time-delay</param> /// <param name="userFunc">Input User Function for customization and diversity</param> /// <returns>List of templates.</returns> public static List <TemplatePyramid> buildTemplate(Gray <byte>[,] image, int Width, int Height, bool buildXMLTemplateFile = false, int angles = 360, int sizes = 1, float minRatio = 0.6f, int[] maxFeaturesPerLevel = null, Func <TemplatePyramid, Gray <byte> [, ], TemplatePyramid> userFunc = null) { List <TemplatePyramid> retList = new List <TemplatePyramid>(); float Ratio = 1; Gray <byte>[,] tempIMG; rotateLoad(retList, image, angles, Width, Height, false, userFunc: validateFeatures); for (int i = 0; i < sizes - 1; i++) { Ratio -= (float)(1 - minRatio) / sizes; int width = (int)(image.Width() * Ratio); int height = (int)(image.Height() * Ratio); DotImaging.Primitives2D.Size Nsize = new DotImaging.Primitives2D.Size(width, height); tempIMG = ResizeExtensions_Gray.Resize(image, Nsize, Accord.Extensions.Imaging.InterpolationMode.NearestNeighbor); rotateLoad(retList, tempIMG, angles, Width, Height, false, maxFeaturesPerLevel, image.ToString(), userFunc: userFunc); } if (buildXMLTemplateFile) { XMLTemplateSerializer <ImageTemplatePyramid <ImageTemplate>, ImageTemplate> .ToFile(retList, Path.Combine(Directory.GetParent(Directory.GetCurrentDirectory()).FullName, "Resources", "template" + ".xml")); } return(retList); }
/// <summary> /// Creates a Rectangle from Point and Size values. /// </summary> /// <param name="location">Location.</param> /// <param name="size">Size.</param> public Rectangle(Point location, Size size) { x = location.X; y = location.Y; width = size.Width; height = size.Height; }
/// <summary> /// Clamps point coordinate according to the specified size (0,0, size.Width, size.Height). /// </summary> /// <param name="point">The point to clamp.</param> /// <param name="size">The valid region.</param> /// <returns>Clamped point.</returns> public static Point Clamp(this Point point, Size size) { return new Point { X = System.Math.Min(System.Math.Max(0, point.X), size.Width), Y = System.Math.Min(System.Math.Max(0, point.Y), size.Height) }; }
/// <summary> /// Creates new video writer. /// </summary> /// <param name="fileName">Video file name.</param> /// <param name="frameSize">Video frame size.</param> /// <param name="fps">Specifies the number of frames per second.</param> /// <param name="isColor">Specifies whether the image is color image (3 channels) or grayscale image (one channel).</param> /// <param name="videoCodec">Specifies used codec for video encoding.</param> public VideoWriter(string fileName, Size frameSize, float fps, bool isColor, VideoCodec videoCodec) { this.CanSeek = false; this.IsLiveStream = true; this.OutputFileName = fileName; this.ColorFrames = isColor; this.Codec = videoCodec; this.FrameSize = frameSize; this.FrameRate = fps; this.Open(); //to enable property change }
/// <summary> /// Inflates the rectangle by specified width and height (can be negative) and automatically clamps rectangle coordinates. /// </summary> /// <param name="rect">Rectangle to inflate.</param> /// <param name="widthScale">Horizontal scale.</param> /// <param name="heightScale">Vertical scale.</param> /// <param name="constrainedArea">If specified rectangle region will be clamped.</param> /// <returns>Inflated rectangle.</returns> public static Rectangle Inflate(this Rectangle rect, double widthScale, double heightScale, Size constrainedArea = default(Size)) { Rectangle newRect = new Rectangle { X = (int)(rect.X - rect.Width * widthScale / 2), Y = (int)(rect.Y - rect.Height * heightScale / 2), Width = (int)(rect.Width + rect.Width * widthScale), Height = (int)(rect.Height + rect.Height * heightScale) }; if (constrainedArea.IsEmpty == false) newRect.Intersect(new Rectangle(new Point(), constrainedArea)); return newRect; }
/// <summary> /// Inflates the rectangle by specified width and height (can be negative) and automatically clamps rectangle coordinates. /// </summary> /// <param name="rect">Rectangle to inflate.</param> /// <param name="width">Horizontal amount.</param> /// <param name="height">Vertical amount.</param> /// <param name="constrainedArea">If specified rectangle region will be clamped.</param> /// <returns>Inflated rectangle.</returns> public static Rectangle Inflate(this Rectangle rect, int width, int height, Size constrainedArea = default(Size)) { Rectangle newRect = new Rectangle { X = rect.X - width, Y = rect.Y - height, Width = rect.Width + 2 * width, Height = rect.Height + 2 * height }; if (constrainedArea.IsEmpty == false) newRect.Intersect(new Rectangle(new Point(), constrainedArea)); return newRect; }
/// <summary> /// Translates a PointF by the negative of a specified size. /// </summary> /// <param name="pt">Point.</param> /// <param name="sz">Offset.</param> /// <returns>PointF structure.</returns> public static PointF Subtract(PointF pt, Size sz) { return new PointF(pt.X - sz.Width, pt.Y - sz.Height); }
/// <summary> /// Translates a PointF by the positive of a specified size. /// </summary> /// <param name="pt">Point.</param> /// <param name="sz">Offset.</param> /// <returns>PointF structure.</returns> public static PointF Add(PointF pt, Size sz) { return new PointF(pt.X + sz.Width, pt.Y + sz.Height); }
public static bool SetImageSize(IntPtr capturePtr, Size newSize) { bool success; success = CvHighGuiInvoke.cvSetCaptureProperty(capturePtr, CaptureProperty.FrameWidth, newSize.Width); success &= CvHighGuiInvoke.cvSetCaptureProperty(capturePtr, CaptureProperty.FrameHeight, newSize.Height); return success; }
public static extern IntPtr cvCreateVideoWriter([MarshalAs(UnmanagedType.LPStr)] String filename, int fourcc, double fps, Size frameSize, [MarshalAs(UnmanagedType.Bool)] bool isColor);
/// <summary> /// Creates a Point from a Size value. /// </summary> /// <param name="sz">Size.</param> public Point(Size sz) { x = sz.Width; y = sz.Height; }
/// <summary> /// build template List from a XML file /// </summary> /// <param name="filename">input XML file name, the file has to be in the current directory </param> /// <param name="buildXMLTemplateFile">true to build a xml file with current templates</param> /// <param name="angles">the number of angles, default to 360</param> /// <param name="sizes">number of sizes, default to 1</param> /// <param name="CropToSqr">decides whether to crop the image to sqrside to prevent edges issues</param> /// <param name="maxFeaturesPerLevel">the array of maximum features per pyrimid level, default (null) would evaluate to 200 in DEFAULT_MAX_FEATURES_PER_LEVEL from ImageTemplatePyramid.cs:56, /// increase to increase the precision in expense of detection time-delay</param> /// <param name="userFunc">Input User Function for customization and diversity</param> /// <returns>List of templates.</returns> public static List <TemplatePyramid> fromFiles(String[] files, bool buildXMLTemplateFile = false, int angles = 360, int sizes = 1, bool CropToSqr = false, int[] maxFeaturesPerLevel = null, Func <TemplatePyramid, Gray <byte> [, ], TemplatePyramid> userFunc = null) { Console.WriteLine("Building templates from files..."); Gray <byte>[,] ResizedtemplatePic; var list = new List <TemplatePyramid>(); string resourceDir = Path.Combine(Directory.GetParent(Directory.GetCurrentDirectory()).FullName, "Resources"); //string[] files = Directory.GetFiles(resourceDir, fileName); if (files.Length == 0) { throw new Exception("NO FILE FOUND"); } object syncObj = new object(); foreach (var file in files) { int shortSide, SqrSide, inputWidth, inputHeight; float FileRatio = 1; Gray <byte>[,] preparedBWImage; for (int j = 0; j < sizes; j++) { Console.WriteLine("Size # " + j); try { preparedBWImage = ImageIO.LoadGray(file).Clone(); } catch { Console.WriteLine("Error occurs when loading " + file); continue; } FileRatio -= (float)0.01; int width = (int)(preparedBWImage.Width() * FileRatio); int height = (int)(preparedBWImage.Height() * FileRatio); if (FileRatio < 0) { Console.WriteLine("Too many sizes to build, Max 100"); FileRatio = 1; break; } DotImaging.Primitives2D.Size Nsize = new DotImaging.Primitives2D.Size(width, height); ResizedtemplatePic = ResizeExtensions_Gray.Resize(preparedBWImage, Nsize, Accord.Extensions.Imaging.InterpolationMode.NearestNeighbor); try { //var tp = TemplatePyramid.CreatePyramidFromPreparedBWImage(preparedBWImage, new FileInfo(file + " " + i * 10).Name, ImageAngle, maxNumberOfFeaturesPerLevel: maxFeaturesPerLevel); shortSide = (preparedBWImage.Width() < preparedBWImage.Height()) ? preparedBWImage.Width() : preparedBWImage.Height(); SqrSide = (int)(shortSide / Math.Sqrt(2)); inputWidth = CropToSqr ? SqrSide : preparedBWImage.Width(); inputHeight = CropToSqr ? SqrSide : preparedBWImage.Height(); rotateLoad(list, preparedBWImage, angles, inputWidth, inputHeight, false, maxFeaturesPerLevel, file, userFunc); } catch (Exception) { } } //} } if (buildXMLTemplateFile) { XMLTemplateSerializer <ImageTemplatePyramid <ImageTemplate>, ImageTemplate> .ToFile(list, Path.Combine(resourceDir, files[0].Substring(0, files[0].IndexOf(".")) + ".xml")); } return(list); }
/// <summary> /// Creates new video writer (with default codec). /// </summary> /// <param name="fileName">Video file name.</param> /// <param name="frameSize">Video frame size.</param> /// <param name="fps">Specifies the number of frames per second.</param> /// <param name="isColor">Specifies whether the image is color image (3 channels) or grayscale image (one channel).</param> public VideoWriter(string fileName, Size frameSize, float fps = 30, bool isColor = true) : this(fileName, frameSize, fps, isColor, VideoCodec.MotionJpeg) { }
/// <summary> /// Enlarges this rectangle by the specified amount. /// </summary> /// <param name="size">The amount to inflate this rectangle.</param> public void Inflate(Size size) { x -= size.Width; y -= size.Height; Width += size.Width * 2; Height += size.Height * 2; }
/// <summary> /// Calculates the binding rectangle for the given text string when the font is used /// </summary> /// <param name="text">Input string</param> /// <param name="baseline">y-coordinate of the baseline relatively to the bottom-most text point</param> /// <returns>size of the text string. Height of the text does not include the height of character parts that are below the baseline</returns> public Size GetTextSize(string text, int baseline) { var size = new Size(); CvCoreInvoke.cvGetTextSize(text, ref this, ref size, ref baseline); return size; }
/// <summary> /// Adds two Size structures. /// </summary> /// <param name="sz1">First structure.</param> /// <param name="sz2">Second structure.</param> /// <returns>Size structure.</returns> public static Size Add(Size sz1, Size sz2) { return new Size(sz1.Width + sz2.Width, sz1.Height + sz2.Height); }
/// <summary> /// Changes rectangle's location in order to fit the specified area. /// </summary> /// <param name="rect">Rectangle.</param> /// <param name="area">Valid bounding box.</param> /// <param name="translatedRectangle">Translated rectangle.</param> /// <returns>True if the translation exist, false otherwise.</returns> public static bool MoveToFit(this Rectangle rect, Size area, out Rectangle translatedRectangle) { var leftOffset = (rect.X < 0) ? -rect.X : 0; var topOffset = (rect.Y < 0) ? -rect.Y : 0; rect.X += leftOffset; rect.Y += topOffset; var rightOffset = (rect.Right > area.Width) ? (area.Width - rect.Right) : 0; var bottomOffset = (rect.Bottom > area.Height) ? (area.Height - rect.Bottom) : 0; rect.X += rightOffset; rect.Y += bottomOffset; translatedRectangle = rect; if (rect.X < 0 || rect.Y < 0 || rect.Right > area.Width || rect.Bottom > area.Height) return false; return true; }
/// <summary> /// Calculates intersected rectangle from specified area (transformed into rectangle with location (0,0)) /// which can be useful for image area intersections. /// </summary> /// <param name="rect">Rectangle to intersect.</param> /// <param name="area">Maximum bounding box represented as size.</param> /// <param name="preserveScale"> /// If true the size components will be cropped by equal amount. /// If false the size ratio will not be checked. /// </param> /// <returns>Intersected rectangle.</returns> public static Rectangle Intersect(this Rectangle rect, Size area, bool preserveScale = false) { Rectangle newRect = rect.Intersect(new Rectangle(0, 0, area.Width, area.Height), preserveScale); return newRect; }
public static unsafe extern void cvEllipse(IplImage* img, Point center, Size axes, double angle, double startAngle, double endAngle, CvScalar color, int thickness, LineTypes lineType, int shift);
public static extern void cvGetTextSize([MarshalAs(UnmanagedType.LPStr)] String textString, ref Font font, ref Size textSize, ref int baseline);
/// <summary> /// Subtracts two Size structures. /// </summary> /// <param name="sz1">First structure.</param> /// <param name="sz2">Second structure.</param> /// <returns>Size structure.</returns> public static Size Subtract(Size sz1, Size sz2) { return new Size(sz1.Width - sz2.Width, sz1.Height - sz2.Height); }
/// <summary> /// Build template with the cemara /// /// State Machine----> /// int -> build template -> resize to find the best -> draw the template then comfirm by user -> /// rotate for angles ->done and return /// /// make sure the object is in green circle /// </summary> /// <param name="name">template name, default to "Template" if the name is null</param> /// <param name="templPyrs">the template list that to be used</param /// <param name="videoCapture">the video stream</param> /// <param name="pictureBox">the picture box of window form</param> /// <param name="minRatio">The ratio of smallest size to original, default to 0.4</param> /// /// <returns>nothing.</returns> public void TemplateCapture(ref List <TemplatePyramid> templPyrs, ImageStreamReader videoCapture, PictureBox pictureBox, string name = null, float minCalibrationRatio = 0.4f) { if (name == null) { name = "Template"; } #if runXML try { Console.WriteLine("Reading from existing Template Data"); templPyrs = fromXML(name); Cap = State.Done; } catch (Exception) { Console.WriteLine("\nTemplate NOT found! \n initiating camera..."); } #endif switch (Cap) { case State.Init: videoCapture.ReadTo(ref frame); if (frame == null) { return; } drawFrameWork(frame); pictureBox.Image = frame.ToBitmap(); //it will be just casted (data is shared) 24bpp color GC.Collect(); break; case State.BuildingTemplate: Console.WriteLine("building template"); videoCapture.ReadTo(ref frame); if (frame == null) { return; } templatePic = frame.ToGray(); //var list = new List<TemplatePyramid>(); try { if (templPyrs == null) { templPyrs = new List <TemplatePyramid>(); } rotateLoad(templPyrs, templatePic, 1, frame.Width(), frame.Height(), userFunc: validateFeatures); } catch (Exception) { Console.WriteLine("ERROR IN CREATING TEMPLATE!"); return; } Cap = State.Calibrate; break; case State.Calibrate: Console.WriteLine("calibrating template " + CabRatio + " " + templatePic.Width() * CabRatio); var bestRepresentatives = findObjects(frame, templPyrs); if (bestRepresentatives.Count == 0) { if (templPyrs.Count != 0) { templPyrs.RemoveAt(templPyrs.Count - 1); } CabRatio -= (float)0.01; int width = (int)(templatePic.Width() * CabRatio); int height = (int)(templatePic.Height() * CabRatio); if (CabRatio < minCalibrationRatio) { Console.WriteLine("Calibration failed"); CabRatio = 1; Cap = State.Init; } DotImaging.Primitives2D.Size Nsize = new DotImaging.Primitives2D.Size(width, height); ResiizedtemplatePic = ResizeExtensions_Gray.Resize(templatePic, Nsize, Accord.Extensions.Imaging.InterpolationMode.NearestNeighbor); try { templPyrs.Add(TemplatePyramid.CreatePyramidFromPreparedBWImage( ResiizedtemplatePic, new FileInfo(name + " #" + TPindex++).Name, 0)); } catch (Exception) { Console.WriteLine("ERROR IN CALIBRATING TEMPLATE!"); } } else { ResiizedtemplatePic = (ResiizedtemplatePic == null ? templatePic : ResiizedtemplatePic); CaptureFrame(templPyrs, videoCapture, pictureBox); drawFrameWork(frame); pictureBox.Image = frame.ToBitmap(); //it will be just casted (data is shared) 24bpp color Cap = State.Confirm; } break; case State.Confirm: Console.WriteLine("comfirm Template, press Y to continue, press R to retry, and other keys to abort"); string a = Console.ReadLine(); switch (a) { case "y": Cap = State.Rotate; break; case "r": templPyrs.RemoveAt(templPyrs.Count - 1); Cap = State.Init; break; default: Cap = State.Done; break; } //if (a == "y") Cap = State.Rotate; //else //{ // Cap = State.Init; //} break; case State.Rotate: int SqrSide = (int)(frame.Height() / Math.Sqrt(2)); templPyrs.AddRange(buildTemplate(ResiizedtemplatePic, SqrSide, SqrSide, false, totalAngles, totalSizes, 0.5f, null, validateFeatures)); //ResiizedtemplatePic, totalAngles, SqrSide, SqrSide, true, userFunc: validateFeatures)); Cap = State.ConfirmDone; break; case State.ConfirmDone: Console.WriteLine("Do you want to build a new template? press y to build another template, other keys to abort"); string OtherTemplate = Console.ReadLine(); if (OtherTemplate == "y" || OtherTemplate == "Y") { Cap = State.Init; } else { string resourceDir = Path.Combine(Directory.GetParent(Directory.GetCurrentDirectory()).FullName, "Resources"); XMLTemplateSerializer <ImageTemplatePyramid <ImageTemplate>, ImageTemplate> .ToFile(templPyrs, Path.Combine(resourceDir, name + ".xml")); Cap = State.Done; } break; //break; case State.Done: CaptureFrame(templPyrs, videoCapture, pictureBox); GC.Collect(); break; //break; } pictureBox.Image = frame.ToBitmap(); //it will be just casted (data is shared) 24bpp color }