/// <summary> /// Creates a traffic sign /// </summary> /// <param name="image"> image of the sign </param> /// <param name="name"> name of the sign </param> public TrafficSign(Image <Bgr, byte> image, string name) { ImageOriginal = image; Emgu.CV.CvEnum.Inter inter = image.Height > SignHeight ? Emgu.CV.CvEnum.Inter.Area : Emgu.CV.CvEnum.Inter.Cubic; ImageGray = image.Convert <Gray, byte>().Resize(int.MaxValue, SignHeight, inter, true); Name = name; InitMatcher(); IsKnownSign = true; }
/// <summary> /// Creates a traffic sign /// </summary> /// <param name="Image"> image of the sign </param> public TrafficSign(Image <Bgr, byte> Image) { ImageOriginal = Image; Emgu.CV.CvEnum.Inter inter = Image.Height > SignHeight ? Emgu.CV.CvEnum.Inter.Area : Emgu.CV.CvEnum.Inter.Cubic; ImageGray = Image.Convert <Gray, byte>().Resize(int.MaxValue, SignHeight, inter, true); Name = null; matcher = null; IsKnownSign = false; }
// Divides area of real mozaic into blocks, separated by frame walls. // If whole number of blocks doesn't fit into given area its margins are cropped. // Finally, given image is resized so that its every pixel corresponds to a color block. // Color of each block is interpolated from its neighbourhood according to given interpolation method. // // If image cannot be fragmented (e.g. when even one block won't fit real mozaic), null is returned. public static FragmentationResult FragmentImage( Image <Bgr, byte> image, SizeF realSize, double blockSize, double frameSize, // size of frame between blocks Emgu.CV.CvEnum.Inter interpolationMethod = Emgu.CV.CvEnum.Inter.Cubic ) { // Compute how many blocks will fit into image, taking into account spacing between them // Number of frame sides is equal to number of blocks + 1, thats why frameSize is substracted from real size double blockWithFrame = blockSize + frameSize; int rows = (int)((realSize.Height - frameSize) / blockWithFrame); int cols = (int)((realSize.Width - frameSize) / blockWithFrame); if (rows == 0 || cols == 0) { // Not even one block would fit return(null); } // Actual size of mozaic double actualHeight = rows * blockSize + (rows + 1) * frameSize; double actualWidth = cols * blockSize + (cols + 1) * frameSize; // Amount of image which needs to be cut from each side // It will also define top-left of mozaic on image double marginTop = (realSize.Height - frameSize - rows * blockWithFrame) / 2; double marginLeft = (realSize.Width - frameSize - cols * blockWithFrame) / 2; // Relative values (in range [0-1]) double topRelative = marginTop / realSize.Height; double leftRelative = marginLeft / realSize.Width; double heightRelative = actualHeight / realSize.Height; double widthRelative = actualWidth / realSize.Width; int topPixel = (int)(topRelative * image.Rows); int leftPixel = (int)(leftRelative * image.Cols); int heightPixel = (int)(heightRelative * image.Rows); int widthPixel = (int)(widthRelative * image.Cols); // Crop image accroding to computed pixel sizes var cropped = image.GetSubRect(new Rectangle( leftPixel, topPixel, widthPixel, heightPixel )); // Simplest way to pick color for each block will be to up-/downscale image so that each pixel will correspond to one block var resized = image.Resize(cols, rows, interpolationMethod); return(new FragmentationResult() { Blocks = resized, MarginTop = marginTop, MarginLeft = marginLeft }); }
private bool FragmentImage(Image <Bgr, byte> i) { Sizes sizes = ReadSizes(); if (sizes.IsInvalid()) { return(false); } Emgu.CV.CvEnum.Inter interpolationMethod = (Emgu.CV.CvEnum.Inter)interpolationMethodInput.SelectedItem; FragmentationResult result = Fragmenter.FragmentImage( i, new SizeF((float)sizes.realWidth, (float)sizes.realHeight), sizes.blockSize, sizes.frameSize, interpolationMethod ); fragmentedImage = result.Blocks; return(true); }
/// <summary> /// Draws the recognised signs /// </summary> /// <param name="src"> original image to draw on </param> /// <param name="matches"> traffic sign matches </param> /// <param name="rawCandidates"> raw candidates </param> /// <returns> image with signs </returns> private Image <Bgr, byte> DrawSigns(Image <Bgr, byte> src, List <TrafficSignMatch> matches, List <TrafficSign> rawCandidates) { Image <Bgr, byte> result = src.Copy(); rawCandidates.ForEach(candidate => { // Draw candidates result.Draw(candidate.BoundingBoxInScene, new Bgr(255, 20, 20), 1); }); matches.ForEach(match => { // Draw matches bounding boxes result.Draw(match.Candidate.BoundingBoxInScene, new Bgr(50, 255, 50), 3); Image <Bgr, byte> signToDraw = match.KnownSign.ImageOriginal.Clone(); Emgu.CV.CvEnum.Inter inter = match.Candidate.BoundingBoxInScene.Width > signToDraw.Width ? Emgu.CV.CvEnum.Inter.Area : Emgu.CV.CvEnum.Inter.Cubic; signToDraw = signToDraw.Resize(match.Candidate.BoundingBoxInScene.Width, int.MaxValue, inter, true); if (match.Candidate.BoundingBoxInScene.Bottom + match.KnownSign.ImageOriginal.Height > src.Height) { // Draw sign above candidate Point p = match.Candidate.BoundingBoxInScene.Location; p.Offset(0, -signToDraw.Size.Height); result.ROI = new Rectangle(p, signToDraw.Size); } else { // Draw sign below candidate Point p = match.Candidate.BoundingBoxInScene.Location; p.Offset(0, match.Candidate.BoundingBoxInScene.Size.Height); result.ROI = new Rectangle(p, signToDraw.Size); } signToDraw.CopyTo(result); result.ROI = Rectangle.Empty; }); return(result); }
public static Image <Bgr, byte> ResizeImage(Image <Bgr, byte> srcImg, int width, int height, Emgu.CV.CvEnum.Inter interpolationType) { if (width == 0 || height == 0) { return(null); } Image <Bgr, byte> imgScale = new Image <Bgr, byte>(width, height); CvInvoke.Resize(srcImg, imgScale, new System.Drawing.Size(width, height), 0, 0, interpolationType); return(imgScale); }
/// <summary> /// Computes the homography between 2 given rectangles and warps the source image. /// </summary> /// <param name="src"> Source Image </param> /// <param name="srcPoints"> Source rectangle, clockwise point array </param> /// <param name="resPoints"> Destination rectangle, clockwise point array </param> /// <param name="resSize"> Size of the destination image </param> /// <param name="interpolation"> Interpolation type </param> /// <returns> Destination Image </returns> public static Image <Bgr, byte> Render(Image <Bgr, byte> src, Point[] srcPoints, Point[] resPoints, Size resSize, Emgu.CV.CvEnum.Inter interpolation) { Image <Bgr, byte> buffer = new Image <Bgr, byte>(src.Size); if (srcPoints.Length != 4 || resPoints.Length != 4) { return(src); } float[,] roi = { { srcPoints[0].X, srcPoints[0].Y }, { srcPoints[1].X, srcPoints[1].Y }, { srcPoints[2].X, srcPoints[2].Y }, { srcPoints[3].X, srcPoints[3].Y } }; Matrix <float> sourceMat = new Matrix <float>(roi); float[,] target = { { resPoints[0].X, resPoints[0].Y }, { resPoints[1].X, resPoints[1].Y }, { resPoints[2].X, resPoints[2].Y }, { resPoints[3].X, resPoints[3].Y } }; Matrix <float> targetMat = new Matrix <float>(target); Mat transform = CvInvoke.GetPerspectiveTransform(sourceMat, targetMat); CvInvoke.WarpPerspective(src, buffer, transform, resSize, interpolation); return(buffer); }