/// <summary> /// Fire An Image Event /// </summary> /// <param name="image">Image To Event</param> protected static void FireImageEvent(object sender, Guid cardId, Guid imageId, ImageType imageType, Mat image, double angle, float X, float Y, CannyParam cannyParameter = null, ThresholdParm thresholdParmeter = null) { ImageEventArgs eventArgs = new ImageEventArgs(cardId, imageId, imageType, image, angle, X, Y, cannyParameter: cannyParameter, thresholdParamter: thresholdParmeter); if (ImageEvent != null) { ImageEvent(sender: sender, data: eventArgs); } }
public ImageEventArgs(Guid cardId, Guid imageId, ImageType imageType, Mat image, double angle, float x, float y, CannyParam cannyParameter = null, ThresholdParm thresholdParamter = null) { CardId = cardId; ImageId = imageId; ImageType = imageType; Image = image.Clone(); Angle = angle; X = x; Y = y; CannyParameters = cannyParameter; ThresholdParamters = thresholdParamter; }
/// <summary> /// Get Thresold Image /// </summary> /// <returns></returns> public Mat GetThresholdImage(double angle, ThresholdParm thresholdParam) { //double thresold = 130; //double maxValue = 255; if (_thresholdImage.image == null || _thresholdImage.angle != angle || !_thresholdImage.thresholdParm.Equals(thresholdParam)) { using (Mat thresoldImage = new Mat()) { using (Mat rotatedImage = GetRotatedImage(angle)) { CvInvoke.Threshold(rotatedImage, thresoldImage, threshold: thresholdParam.Threshold, maxValue: thresholdParam.MaxValue, thresholdType: ThresholdType.BinaryInv); _thresholdImage.image = thresoldImage.Clone(); _thresholdImage.angle = angle; _thresholdImage.thresholdParm = thresholdParam; } } } return(_thresholdImage.image.Clone()); }
/// <summary> /// Fire the Image Event And Send a Contoured Image /// </summary> protected void FireImageEvent(object sender, Guid cardId, Guid imageId, ImageType imageType, double angle, float X, float Y, CannyParam cannyParameter = null, ThresholdParm thresholdParmeter = null) { if (ImageEvent != null) { using (var image = GetContouredImage(angle, cannyParameter)) { Image.FireImageEvent(null, cardId, imageId, imageType, image, angle, X, Y, cannyParameter); } } }
/// <summary> /// Get a filtered image that is good for OCR /// </summary> public Mat GetFilteredImage(MTGCardFrame cardTitleType, double angle, ThresholdParm thresoldParameter, CannyParam cannyParameter) { if (_filteredImage.image == null || _filteredImage.cannyParam != cannyParameter || _filteredImage.angle != angle) { using (Mat titleImage = GetImage()) { Size titleSize = titleImage.Size; int minX = titleImage.Width; int maxX = titleImage.Height; int minY = 0; int maxY = 0; // Get the Canny Image To Make A Contour Set For the Letters using (Mat titleCannyImage = GetCannyImage(() => { return(GetThresholdImage(angle, thresoldParameter)); }, angle, cannyParameter)) { using (Mat maskedImage = new Mat(titleSize, DepthType.Cv8U, 1)) { // White/black out the mask. Legacy cards are white letters on color, the new style is black letters in a colored title box. maskedImage.SetTo(cardTitleType == MTGCardFrame.M15 ? black : white); using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint()) { CvInvoke.FindContours(titleCannyImage, contours, hierarchy: null, mode: retrType, method: chainApproxMethod); for (int i = 1; i < contours.Size; i++) { using (VectorOfPoint contour = contours[i]) { Rectangle rect = CvInvoke.BoundingRectangle(contour); double relativeY = (double)rect.Y / (double)titleSize.Height; double relativeX = (double)rect.X / (double)titleSize.Width; double relativeBottom = ((double)rect.Y + (double)rect.Height) / (double)titleSize.Height; double relativeRight = ((double)rect.X + (double)rect.Width) / (double)titleSize.Width; double relativeWidth = (double)rect.Width / (double)titleSize.Width; double relativeHeight = (double)rect.Height / (double)titleSize.Height; // The Characters Start In the 10 % of the Title Image, and Complete Within the if (((relativeY > .10) && (relativeY < .80) && (relativeBottom > .30) && (relativeBottom < .95) && (relativeRight > .025) && (relativeX < .95)) && (relativeWidth < .09) && (relativeHeight > .07)) { // Make a mask of rectangles that represent the title. CvInvoke.Rectangle(maskedImage, rect, new MCvScalar(255, 255, 255), -1); // Keep Track Of the Border Area Which Comprises The Letters minX = Math.Min(rect.X, minX); minY = Math.Min(rect.Y, minY); maxX = Math.Max(rect.X + rect.Width, maxX); maxY = Math.Max(rect.Y + rect.Height, maxY); } } } } // The result is the same depth/channels as the thresold using (Mat result = GetThresholdImage(angle, thresoldParameter)) { // Clear the result result.SetTo(cardTitleType == MTGCardFrame.M15 ? black : white); // Use the Mask To Take Just The Title From the thresoldImage GetThresholdImage(angle, thresoldParameter).CopyTo(result, maskedImage); _filteredImage.image = result.Clone(); _filteredImage.cannyParam = cannyParameter; _filteredImage.angle = angle; } } } } } return(_filteredImage.image.Clone()); }