public VectorOfUMat ForwardFt(UMat img) { ///outputs quadrant-rearranged {magnitude, phase} UMat array ///FT stuff, reference: https://docs.opencv.org/master/d8/d01/tutorial_discrete_fourier_transform.html //convert image to 32bit float because spacial frequency domain values are way bigger than spatial domain values. img.ConvertTo(img, DepthType.Cv32F); //create imaginary image of zeros of same depthType and size as image representing real plane UMat zeros = new UMat(img.Size, img.Depth, 1); zeros.SetTo(new MCvScalar(0)); //Dft accepts 2-channel images, so we use Merge to merge our 2 1-channel images into a single 2-channel image. //Merge accepts object arrays, so we create a VectorOfUMat of our 2 images to feed into Merge. VectorOfUMat vec = new VectorOfUMat(img, zeros); //img will be at 0 index of vector using (UMat cImg = new UMat()) { CvInvoke.Merge(vec, cImg); zeros.Dispose(); // TODO: fix this bad programming and other instances of it. CvInvoke.Dft(cImg, cImg, DxtType.Forward, 0); //use back the same image memory SwitchQuadrants(cImg); CvInvoke.Split(cImg, vec); } //make the 2-channel array into 2 1-channel arrays return(vec); //[0] index contains the real values and [1] index the complex values }
public VectorOfUMat InverseFt(UMat re, UMat im) { ///reference: https://stackoverflow.com/questions/16812950/how-do-i-compute-dft-and-its-reverse-with-emgu VectorOfUMat vec = new VectorOfUMat(re, im); using (UMat cImg = new UMat()) { CvInvoke.Merge(vec, cImg); //because Dft method accepts and outputs 2-channel image CvInvoke.Dft(cImg, cImg, DxtType.Inverse, 0); CvInvoke.Split(cImg, vec); } return(vec); }
/* * /// <summary> * /// Convert this Mat to UMat * /// </summary> * /// <param name="access">Access type</param> * /// <returns>The UMat</returns> * public Mat ToMat(CvEnum.AccessType access) * { * return new Mat(UMatInvoke.cvUMatGetMat(Ptr, access), true); * }*/ ///<summary> ///Split current Image into an array of gray scale images where each element ///in the array represent a single color channel of the original image ///</summary> ///<returns> ///An array of gray scale images where each element ///in the array represent a single color channel of the original image ///</returns> public UMat[] Split() { UMat[] mats = new UMat[NumberOfChannels]; for (int i = 0; i < mats.Length; i++) { mats[i] = new UMat(Rows, Cols, Depth, NumberOfChannels); } using (VectorOfUMat vm = new VectorOfUMat(mats)) { CvInvoke.Split(this, vm); } return(mats); }
public static UMat getSaturationAdjusted(ref UMat img, double amount) { Image <Hsv, double> outImg = img.ToImage <Hsv, double>(); UMat dblImg = new UMat(img.Rows, img.Cols, Emgu.CV.CvEnum.DepthType.Cv64F, img.NumberOfChannels); outImg = img.ToImage <Hsv, double>(); var colors = new VectorOfUMat(3); CvInvoke.Split(outImg, colors); double shift = (1 + amount) >= 0.0 ? 1 + amount : 0; CvInvoke.AddWeighted(colors[1], shift, colors[1], 0, 0, colors[1]); CvInvoke.Merge(colors, dblImg); return(dblImg); }
/* * /// <summary> * /// Convert this Mat to UMat * /// </summary> * /// <param name="access">Access type</param> * /// <returns>The UMat</returns> * public Mat ToMat(CvEnum.AccessType access) * { * return new Mat(UMatInvoke.cvUMatGetMat(Ptr, access), true); * }*/ ///<summary> ///Split current Image into an array of gray scale images where each element ///in the array represent a single color channel of the original image ///</summary> ///<returns> ///An array of gray scale images where each element ///in the array represent a single color channel of the original image ///</returns> public UMat[] Split() { UMat[] mats = new UMat[NumberOfChannels]; Size s = this.Size; DepthType d = this.Depth; for (int i = 0; i < mats.Length; i++) { mats[i] = new UMat(s, d, 1); } using (VectorOfUMat vm = new VectorOfUMat(mats)) { CvInvoke.Split(this, vm); } return(mats); }
public static UMat getColorAdjusted(ref UMat img, double redshift, double greenshift, double blueshift) { double shift; UMat dblImg = new UMat(img.Rows, img.Cols, Emgu.CV.CvEnum.DepthType.Cv64F, img.NumberOfChannels); img.ConvertTo(dblImg, Emgu.CV.CvEnum.DepthType.Cv64F); var colors = new VectorOfUMat(3); CvInvoke.Split(img, colors); shift = (1 + redshift) > 0 ? (1 + redshift) : 0; CvInvoke.AddWeighted(colors[2], shift, colors[2], 0, 0, colors[2]); shift = (1 + greenshift) > 0 ? (1 + greenshift) : 0; CvInvoke.AddWeighted(colors[1], shift, colors[1], 0, 0, colors[1]); shift = (1 + blueshift) > 0 ? (1 + blueshift) : 0; CvInvoke.AddWeighted(colors[0], shift, colors[0], 0, 0, colors[0]); CvInvoke.Merge(colors, dblImg); img.Dispose(); return(dblImg); }
public void InverseT(UMat reIn, UMat imIn, UMat magOut, UMat phOut) { ///accepts real and imaginary parts, inverse (fourier) Transforms ///converts real and imaginary output parts to magnitude and ///phase, returns magnitude and phase parts. ///Refer to ForwardT() for more info on why I code like this. ///Reference: https://stackoverflow.com/questions/16812950/how-do-i-compute-dft-and-its-reverse-with-emgu VectorOfUMat vec = this.vec; vec.Push(reIn); vec.Push(imIn); UMat cImg = this.img32f2c; CvInvoke.Merge(vec, cImg); //because Dft method accepts and outputs 2-channel image CvInvoke.Dft(cImg, cImg, DxtType.Inverse, 0); //new objects put into vec, vec[0] is reOut, vec[1] is imOut. CvInvoke.Split(cImg, vec); //convert output of inverse Transform to magnitude and polar CvInvoke.CartToPolar(vec[0], vec[1], magOut, phOut); vec.Clear(); }
private static String OcrImage(Tesseract ocr, Mat image, OCRMode mode, Mat imageColor) { Bgr drawCharColor = new Bgr(Color.Red); if (image.NumberOfChannels == 1) { CvInvoke.CvtColor(image, imageColor, ColorConversion.Gray2Bgr); } else { image.CopyTo(imageColor); } if (mode == OCRMode.FullPage) { ocr.SetImage(imageColor); if (ocr.Recognize() != 0) { throw new Exception("Failed to recognizer image"); } Tesseract.Character[] characters = ocr.GetCharacters(); if (characters.Length == 0) { Mat imgGrey = new Mat(); CvInvoke.CvtColor(image, imgGrey, ColorConversion.Bgr2Gray); Mat imgThresholded = new Mat(); CvInvoke.Threshold(imgGrey, imgThresholded, 65, 255, ThresholdType.Binary); ocr.SetImage(imgThresholded); characters = ocr.GetCharacters(); imageColor = imgThresholded; if (characters.Length == 0) { CvInvoke.Threshold(image, imgThresholded, 190, 255, ThresholdType.Binary); ocr.SetImage(imgThresholded); characters = ocr.GetCharacters(); imageColor = imgThresholded; } } foreach (Tesseract.Character c in characters) { CvInvoke.Rectangle(imageColor, c.Region, drawCharColor.MCvScalar); } return(ocr.GetUTF8Text()); } else { bool checkInvert = true; Rectangle[] regions; using ( ERFilterNM1 er1 = new ERFilterNM1("trained_classifierNM1.xml", 8, 0.00025f, 0.13f, 0.4f, true, 0.1f)) using (ERFilterNM2 er2 = new ERFilterNM2("trained_classifierNM2.xml", 0.3f)) { int channelCount = image.NumberOfChannels; UMat[] channels = new UMat[checkInvert ? channelCount * 2 : channelCount]; for (int i = 0; i < channelCount; i++) { UMat c = new UMat(); CvInvoke.ExtractChannel(image, c, i); channels[i] = c; } if (checkInvert) { for (int i = 0; i < channelCount; i++) { UMat c = new UMat(); CvInvoke.BitwiseNot(channels[i], c); channels[i + channelCount] = c; } } VectorOfERStat[] regionVecs = new VectorOfERStat[channels.Length]; for (int i = 0; i < regionVecs.Length; i++) { regionVecs[i] = new VectorOfERStat(); } try { for (int i = 0; i < channels.Length; i++) { er1.Run(channels[i], regionVecs[i]); er2.Run(channels[i], regionVecs[i]); } using (VectorOfUMat vm = new VectorOfUMat(channels)) { regions = ERFilter.ERGrouping(image, vm, regionVecs, ERFilter.GroupingMethod.OrientationHoriz, "trained_classifier_erGrouping.xml", 0.5f); } } finally { foreach (UMat tmp in channels) { if (tmp != null) { tmp.Dispose(); } } foreach (VectorOfERStat tmp in regionVecs) { if (tmp != null) { tmp.Dispose(); } } } Rectangle imageRegion = new Rectangle(Point.Empty, imageColor.Size); for (int i = 0; i < regions.Length; i++) { Rectangle r = ScaleRectangle(regions[i], 1.1); r.Intersect(imageRegion); regions[i] = r; } } List <Tesseract.Character> allChars = new List <Tesseract.Character>(); String allText = String.Empty; foreach (Rectangle rect in regions) { using (Mat region = new Mat(image, rect)) { ocr.SetImage(region); if (ocr.Recognize() != 0) { throw new Exception("Failed to recognize image"); } Tesseract.Character[] characters = ocr.GetCharacters(); //convert the coordinates from the local region to global for (int i = 0; i < characters.Length; i++) { Rectangle charRegion = characters[i].Region; charRegion.Offset(rect.Location); characters[i].Region = charRegion; } allChars.AddRange(characters); allText += ocr.GetUTF8Text() + Environment.NewLine; } } Bgr drawRegionColor = new Bgr(Color.Red); foreach (Rectangle rect in regions) { CvInvoke.Rectangle(imageColor, rect, drawRegionColor.MCvScalar); } foreach (Tesseract.Character c in allChars) { CvInvoke.Rectangle(imageColor, c.Region, drawCharColor.MCvScalar); } return(allText); } }
public void ProcessForwardT(UMat inImg, UMat outMagT, UMat outPhT, bool zeroPad = false, bool switchQuadrants = true) { ///Accepts a 1-channel image, updates outMagT and outPhT. ///magnitude and phase, cause I can't think of why you ///would wanna look at real and imaginary Transforms. ///Also can't think of how you can get complex-valued images. ///Quadrant rearranging doesn't support odd rows or cols. ///T stuff, reference: https://docs.opencv.org/master/d8/d01/tutorial_discrete_fourier_transform.html //convert image to 32bit float because spacial frequency //domain values are way bigger than spatial domain values. UMat re = outMagT; //32-bit float real image, use memory from //outMagT cause it's gonna be updated anyway inImg.ConvertTo(re, DepthType.Cv32F); if (zeroPad) { //zero pad for faster dft ZeroPadImage(re); } //create imaginary image of zeros of same depthType //and size as image representing real plane UMat im = outPhT; //imaginary im.Create(re.Rows, re.Cols, re.Depth, re.NumberOfChannels); //allocate memory so you can set it to zero array //if memory hasn't already been allocated for it im.SetTo(new MCvScalar(0)); /// Quick exerpt about VectorOfUMat: /// if you create a VectorOfUMat vec, only if the first UMat variable /// to store the object is the vector node, like /// VectorOfUMat vec = new VectorOfUmat(new Umat(), new Umat()); /// vec.Push(someUMat.Clone()); /// then vec.Dispose/Clear actually disposes all the objects referenced /// to by the UMats in vec. In this case, if you did: /// VectorOfUMat vec = new VectorOfUMat(inImg.Clone(), inImg.Clone()); /// UMat one = vec[0]; /// one.Dispose(); /// one.Dispose actually does nothing. /// Otherwise, if /// UMat one = new UMat(); /// UMat two = new UMat(); /// VectorOfUMat vec = new VectorOfUmat(one); /// vec.Push(two); /// calling vec.Dispose() doesn't dispose the objects. /// you have to call one.Dispose and two.Dispose. /// Note: no matter whether the UMat's first variable stored /// in is in a vector node or not, calling vec[index].Dispose /// does NOTHING. /// The situation is the same for vec.Clear, except Clear doesn't /// dispose of vec itself, it just disposes the objects the UMats in /// it reference to. //Dft accepts 2-channel images, so we use Merge to merge //our 2 1-channel images into a single 2-channel image. //Merge accepts object arrays, so we create a VectorOfUMat //of our 2 images to feed into Merge. VectorOfUMat vec = this.vec; UMat cImg = this.img32f2c; vec.Push(re); vec.Push(im); //vec[0] = re, vec[1] = im ; CvInvoke.Merge(vec, cImg); CvInvoke.Dft(cImg, cImg, DxtType.Forward, 0); //use back the same memory //switch quadrants while images are still combined if (switchQuadrants) { SwitchQuadrants(cImg); } //make the 2-channel array into 2 1-channel arrays CvInvoke.Split(cImg, vec); //vec[0] is reT, vec[1] is imT, they are new objects. CvInvoke.CartToPolar(vec[0], vec[1], outMagT, outPhT); vec.Clear(); //dispose reT and imT.TODO: find a way to get rid of allocating memory for reT and imT. }
public void TestERFilter() { CvInvoke.SanityCheck(); bool checkInvert = true; using (Image<Bgr, Byte> image = EmguAssert.LoadImage<Bgr, Byte>("scenetext01.jpg")) using (ERFilterNM1 er1 = new ERFilterNM1(EmguAssert.GetFile("trained_classifierNM1.xml"), 8, 0.00025f, 0.13f, 0.4f, true, 0.1f)) using (ERFilterNM2 er2 = new ERFilterNM2(EmguAssert.GetFile("trained_classifierNM2.xml"), 0.3f)) { //using (Image<Gray, Byte> mask = new Image<Gray,byte>(image.Size.Width + 2, image.Size.Height + 2)) int channelCount = image.NumberOfChannels; UMat[] channels = new UMat[checkInvert ? channelCount * 2 : channelCount]; for (int i = 0; i < channelCount; i++) { UMat c = new UMat(); CvInvoke.ExtractChannel(image.Mat, c, i); channels[i] = c; } if (checkInvert) { for (int i = 0; i < channelCount; i++) { UMat c = new UMat(); CvInvoke.BitwiseNot(channels[i], c); channels[i + channelCount] = c; } } VectorOfERStat[] regionVecs = new VectorOfERStat[channels.Length]; for (int i = 0; i < regionVecs.Length; i++) regionVecs[i] = new VectorOfERStat(); /* for (int i = 0; i < channels.Length; i++) { Emgu.CV.UI.ImageViewer.Show(channels[i]); }*/ try { for (int i = 0; i < channels.Length; i++) { er1.Run(channels[i], regionVecs[i]); er2.Run(channels[i], regionVecs[i]); } using (VectorOfUMat vm = new VectorOfUMat(channels)) { Rectangle[] regions = ERFilter.ERGrouping(image, vm, regionVecs, ERFilter.GroupingMethod.OrientationHoriz, EmguAssert.GetFile("trained_classifier_erGrouping.xml"), 0.5f); foreach (Rectangle rect in regions) image.Draw(rect, new Bgr(0, 0, 255), 2); } } finally { foreach (UMat tmp in channels) if (tmp != null) tmp.Dispose(); foreach (VectorOfERStat tmp in regionVecs) if (tmp != null) tmp.Dispose(); } //Emgu.CV.UI.ImageViewer.Show(image); } }
public void TestDenseHistogram3() { UMat img = new UMat(400, 400, DepthType.Cv8U, 3); CvInvoke.Randu(img, new MCvScalar(), new MCvScalar(255, 255, 255)); UMat hist = new UMat(); using (VectorOfUMat vms = new VectorOfUMat(img)) { CvInvoke.CalcHist(vms, new int[] { 0, 1, 2 }, null, hist, new int[] { 20, 20, 20 }, new float[] { 0, 255, 0, 255, 0, 255 }, true); byte[] bytes = hist.Bytes; hist.SetTo(bytes); float[] bins = new float[20 * 20 * 20]; hist.CopyTo(bins); } }
private void loadImageButton_Click(object sender, EventArgs e) { if (openImageFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { fileNameTextBox.Text = openImageFileDialog.FileName; imageBox1.Image = null; ocrTextBox.Text = String.Empty; hocrTextBox.Text = String.Empty; Bgr drawCharColor = new Bgr(Color.Blue); try { Mat image = new Mat(openImageFileDialog.FileName, ImreadModes.AnyColor); Mat imageColor = new Mat(); if (image.NumberOfChannels == 1) { CvInvoke.CvtColor(image, imageColor, ColorConversion.Gray2Bgr); } else { image.CopyTo(imageColor); } if (Mode == OCRMode.FullPage) { _ocr.Recognize(image); Tesseract.Character[] characters = _ocr.GetCharacters(); if (characters.Length == 0) { Mat imgGrey = new Mat(); CvInvoke.CvtColor(image, imgGrey, ColorConversion.Bgr2Gray); Mat imgThresholded = new Mat(); CvInvoke.Threshold(imgGrey, imgThresholded, 65, 255, ThresholdType.Binary); _ocr.Recognize(imgThresholded); characters = _ocr.GetCharacters(); imageColor = imgThresholded; if (characters.Length == 0) { CvInvoke.Threshold(image, imgThresholded, 190, 255, ThresholdType.Binary); _ocr.Recognize(imgThresholded); characters = _ocr.GetCharacters(); imageColor = imgThresholded; } } foreach (Tesseract.Character c in characters) { CvInvoke.Rectangle(imageColor, c.Region, drawCharColor.MCvScalar); } imageBox1.Image = imageColor; String text = _ocr.GetText(); ocrTextBox.Text = text; String hocrText = _ocr.GetHOCRText(); hocrTextBox.Text = hocrText; } else { bool checkInvert = true; Rectangle[] regions; using (ERFilterNM1 er1 = new ERFilterNM1("trained_classifierNM1.xml", 8, 0.00025f, 0.13f, 0.4f, true, 0.1f)) using (ERFilterNM2 er2 = new ERFilterNM2("trained_classifierNM2.xml", 0.3f)) { int channelCount = image.NumberOfChannels; UMat[] channels = new UMat[checkInvert ? channelCount * 2 : channelCount]; for (int i = 0; i < channelCount; i++) { UMat c = new UMat(); CvInvoke.ExtractChannel(image, c, i); channels[i] = c; } if (checkInvert) { for (int i = 0; i < channelCount; i++) { UMat c = new UMat(); CvInvoke.BitwiseNot(channels[i], c); channels[i + channelCount] = c; } } VectorOfERStat[] regionVecs = new VectorOfERStat[channels.Length]; for (int i = 0; i < regionVecs.Length; i++) { regionVecs[i] = new VectorOfERStat(); } try { for (int i = 0; i < channels.Length; i++) { er1.Run(channels[i], regionVecs[i]); er2.Run(channels[i], regionVecs[i]); } using (VectorOfUMat vm = new VectorOfUMat(channels)) { regions = ERFilter.ERGrouping(image, vm, regionVecs, ERFilter.GroupingMethod.OrientationHoriz, "trained_classifier_erGrouping.xml", 0.5f); } } finally { foreach (UMat tmp in channels) { if (tmp != null) { tmp.Dispose(); } } foreach (VectorOfERStat tmp in regionVecs) { if (tmp != null) { tmp.Dispose(); } } } Rectangle imageRegion = new Rectangle(Point.Empty, imageColor.Size); for (int i = 0; i < regions.Length; i++) { Rectangle r = ScaleRectangle(regions[i], 1.1); r.Intersect(imageRegion); regions[i] = r; } } List <Tesseract.Character> allChars = new List <Tesseract.Character>(); String allText = String.Empty; foreach (Rectangle rect in regions) { using (Mat region = new Mat(image, rect)) { _ocr.Recognize(region); Tesseract.Character[] characters = _ocr.GetCharacters(); //convert the coordinates from the local region to global for (int i = 0; i < characters.Length; i++) { Rectangle charRegion = characters[i].Region; charRegion.Offset(rect.Location); characters[i].Region = charRegion; } allChars.AddRange(characters); allText += _ocr.GetText() + Environment.NewLine; } } Bgr drawRegionColor = new Bgr(Color.Red); foreach (Rectangle rect in regions) { CvInvoke.Rectangle(imageColor, rect, drawRegionColor.MCvScalar); } foreach (Tesseract.Character c in allChars) { CvInvoke.Rectangle(imageColor, c.Region, drawCharColor.MCvScalar); } imageBox1.Image = imageColor; ocrTextBox.Text = allText; } } catch (Exception exception) { MessageBox.Show(exception.Message); } } }
public void generateChannels(Image <Bgr, byte> img_original, string image_name, string destination_folder) { Directory.CreateDirectory(destination_folder); //string destination_folder = tbDestination.Text; img_original = img_original.SmoothGaussian(3); //smooth gaussian Image <Luv, byte> luv; //will contain luv image to extract LUV channels luv = img_original.Convert <Luv, byte>(); //convert from bgr to luv VectorOfUMat channels = new VectorOfUMat(); //contains luv channels CvInvoke.Split(luv, channels); //split them Image <Gray, double> image_channel_L = channels[0].ToImage <Gray, double>(); //L channel image_channel_L = image_channel_L.SmoothGaussian(3); Image <Gray, double> image_channel_U = channels[1].ToImage <Gray, double>(); //U channel image_channel_U = image_channel_U.SmoothGaussian(3); Image <Gray, double> image_channel_V = channels[2].ToImage <Gray, double>(); //V channel image_channel_V = image_channel_V.SmoothGaussian(3); CvInvoke.Imwrite(@destination_folder + "__L.jpg", image_channel_L); CvInvoke.Imwrite(@destination_folder + "__U.jpg", image_channel_U); CvInvoke.Imwrite(@destination_folder + "__V.jpg", image_channel_V); Mat gray = new Mat(); //gray version of the original image Mat grad = new Mat(); //will contain the gradient magnitude Mat grad_x = new Mat(); //sobel x Mat grad_y = new Mat(); //sobel y Mat abs_grad_x = new Mat(); //abs Mat abs_grad_y = new Mat(); Mat angles = new Mat(); //matrix will contain the angle of every edge in grad magnitude channel CvInvoke.CvtColor(img_original, gray, Emgu.CV.CvEnum.ColorConversion.Bgr2Gray); //get gray image from bgr //channels defined below will contain the edges in different angles Image <Gray, UInt16> C1 = new Image <Gray, UInt16>(img_original.Cols, img_original.Rows); Image <Gray, UInt16> C2 = new Image <Gray, UInt16>(img_original.Cols, img_original.Rows); Image <Gray, UInt16> C3 = new Image <Gray, UInt16>(img_original.Cols, img_original.Rows); Image <Gray, UInt16> C4 = new Image <Gray, UInt16>(img_original.Cols, img_original.Rows); Image <Gray, UInt16> C5 = new Image <Gray, UInt16>(img_original.Cols, img_original.Rows); Image <Gray, UInt16> C6 = new Image <Gray, UInt16>(img_original.Cols, img_original.Rows); //apply sobel CvInvoke.Sobel(gray, grad_x, Emgu.CV.CvEnum.DepthType.Cv32F, 1, 0, 3); CvInvoke.ConvertScaleAbs(grad_x, abs_grad_x, 1, 0); CvInvoke.Sobel(gray, grad_y, Emgu.CV.CvEnum.DepthType.Cv32F, 0, 1, 3); CvInvoke.ConvertScaleAbs(grad_y, abs_grad_y, 1, 0); CvInvoke.AddWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad); Image <Gray, UInt16> img_gradient = grad.ToImage <Gray, UInt16>(); //will store gradient magnitude as an image img_gradient = normalize(img_gradient); CvInvoke.Imwrite(@destination_folder + "__G.jpg", img_gradient); Emgu.CV.Cuda.CudaInvoke.Phase(grad_x, grad_y, angles, true); //get angles Image <Gray, double> img_angles = angles.ToImage <Gray, double>(); //stores the angles as a gray image //loop through angles for (int i = 0; i < img_angles.Height; i++) { for (int j = 0; j < img_angles.Width; j++) { double current_angle = img_angles.Data[i, j, 0]; //current angle value in degrees if (current_angle > 180) //if greater than 180 { img_angles.Data[i, j, 0] = (double)(img_angles.Data[i, j, 0] - 180); //fix it } current_angle = img_angles.Data[i, j, 0]; //update current value //according to the value of the angle, add it to the corresponding channel if (current_angle >= 0 && current_angle <= 30) { addEdgeToChannel(i, j, img_gradient.Data[i, j, 0], C1); } else if (current_angle > 30 && current_angle <= 60) { addEdgeToChannel(i, j, img_gradient.Data[i, j, 0], C2); } else if (current_angle > 60 && current_angle <= 90) { addEdgeToChannel(i, j, img_gradient.Data[i, j, 0], C3); } else if (current_angle > 90 && current_angle <= 120) { addEdgeToChannel(i, j, img_gradient.Data[i, j, 0], C4); } else if (current_angle > 120 && current_angle <= 150) { addEdgeToChannel(i, j, img_gradient.Data[i, j, 0], C5); } else if (current_angle > 150 && current_angle <= 180) { addEdgeToChannel(i, j, img_gradient.Data[i, j, 0], C6); } } } //smooth channels C1 = C1.SmoothGaussian(3); C2 = C2.SmoothGaussian(3); C3 = C3.SmoothGaussian(3); C4 = C4.SmoothGaussian(3); C5 = C5.SmoothGaussian(3); C6 = C6.SmoothGaussian(3); CvInvoke.Imwrite(@destination_folder + "__C1.jpg", C1); CvInvoke.Imwrite(@destination_folder + "__C2.jpg", C2); CvInvoke.Imwrite(@destination_folder + "__C3.jpg", C3); CvInvoke.Imwrite(@destination_folder + "__C4.jpg", C4); CvInvoke.Imwrite(@destination_folder + "__C5.jpg", C5); CvInvoke.Imwrite(@destination_folder + "__C6.jpg", C6); }
private void loadImageButton_Click(object sender, EventArgs e) { if (openImageFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { fileNameTextBox.Text = openImageFileDialog.FileName; imageBox1.Image = null; ocrTextBox.Text = String.Empty; hocrTextBox.Text = String.Empty; Bgr drawCharColor = new Bgr(Color.Blue); try { Mat image = new Mat(openImageFileDialog.FileName, ImreadModes.AnyColor); Mat imageColor = new Mat(); if (image.NumberOfChannels == 1) CvInvoke.CvtColor(image, imageColor, ColorConversion.Gray2Bgr); else image.CopyTo(imageColor); if (Mode == OCRMode.FullPage) { _ocr.Recognize(image); Tesseract.Character[] characters = _ocr.GetCharacters(); if (characters.Length == 0) { Mat imgGrey = new Mat(); CvInvoke.CvtColor(image, imgGrey, ColorConversion.Bgr2Gray); Mat imgThresholded = new Mat(); CvInvoke.Threshold(imgGrey, imgThresholded,65, 255, ThresholdType.Binary); _ocr.Recognize(imgThresholded); characters = _ocr.GetCharacters(); imageColor = imgThresholded; if (characters.Length == 0) { CvInvoke.Threshold(image, imgThresholded, 190, 255, ThresholdType.Binary); _ocr.Recognize(imgThresholded); characters = _ocr.GetCharacters(); imageColor = imgThresholded; } } foreach (Tesseract.Character c in characters) { CvInvoke.Rectangle(imageColor, c.Region, drawCharColor.MCvScalar); } imageBox1.Image = imageColor; String text = _ocr.GetText(); ocrTextBox.Text = text; String hocrText = _ocr.GetHOCRText(); hocrTextBox.Text = hocrText; } else { bool checkInvert = true; Rectangle[] regions; using (ERFilterNM1 er1 = new ERFilterNM1("trained_classifierNM1.xml", 8, 0.00025f, 0.13f, 0.4f, true, 0.1f)) using (ERFilterNM2 er2 = new ERFilterNM2("trained_classifierNM2.xml", 0.3f)) { int channelCount = image.NumberOfChannels; UMat[] channels = new UMat[checkInvert ? channelCount * 2 : channelCount]; for (int i = 0; i < channelCount; i++) { UMat c = new UMat(); CvInvoke.ExtractChannel(image, c, i); channels[i] = c; } if (checkInvert) { for (int i = 0; i < channelCount; i++) { UMat c = new UMat(); CvInvoke.BitwiseNot(channels[i], c); channels[i + channelCount] = c; } } VectorOfERStat[] regionVecs = new VectorOfERStat[channels.Length]; for (int i = 0; i < regionVecs.Length; i++) regionVecs[i] = new VectorOfERStat(); try { for (int i = 0; i < channels.Length; i++) { er1.Run(channels[i], regionVecs[i]); er2.Run(channels[i], regionVecs[i]); } using (VectorOfUMat vm = new VectorOfUMat(channels)) { regions = ERFilter.ERGrouping(image, vm, regionVecs, ERFilter.GroupingMethod.OrientationHoriz, "trained_classifier_erGrouping.xml", 0.5f); } } finally { foreach (UMat tmp in channels) if (tmp != null) tmp.Dispose(); foreach (VectorOfERStat tmp in regionVecs) if (tmp != null) tmp.Dispose(); } Rectangle imageRegion = new Rectangle(Point.Empty, imageColor.Size); for (int i = 0; i < regions.Length; i++) { Rectangle r = ScaleRectangle( regions[i], 1.1); r.Intersect(imageRegion); regions[i] = r; } } List<Tesseract.Character> allChars = new List<Tesseract.Character>(); String allText = String.Empty; foreach (Rectangle rect in regions) { using (Mat region = new Mat(image, rect)) { _ocr.Recognize(region); Tesseract.Character[] characters = _ocr.GetCharacters(); //convert the coordinates from the local region to global for (int i = 0; i < characters.Length; i++) { Rectangle charRegion = characters[i].Region; charRegion.Offset(rect.Location); characters[i].Region = charRegion; } allChars.AddRange(characters); allText += _ocr.GetText() + Environment.NewLine; } } Bgr drawRegionColor = new Bgr(Color.Red); foreach (Rectangle rect in regions) { CvInvoke.Rectangle(imageColor, rect, drawRegionColor.MCvScalar); } foreach (Tesseract.Character c in allChars) { CvInvoke.Rectangle(imageColor, c.Region, drawCharColor.MCvScalar); } imageBox1.Image = imageColor; ocrTextBox.Text = allText; } } catch (Exception exception) { MessageBox.Show(exception.Message); } } }
public string Recognize(Mat image) { Rectangle[] regions; Bgr drawCharColor = new Bgr(Color.Red); using (var er1 = new ERFilterNM1("Assets\\trained_classifierNM1.xml", 8, 0.00025f, 0.13f, 0.4f, true, 0.1f)) { using (var er2 = new ERFilterNM2("Assets\\trained_classifierNM2.xml", 0.3f)) { var channelCount = image.NumberOfChannels; var channels = new UMat[channelCount * 2]; for (int i = 0; i < channelCount; i++) { var c = new UMat(); CvInvoke.ExtractChannel(image, c, i); channels[i] = c; } for (int i = 0; i < channelCount; i++) { var c = new UMat(); CvInvoke.BitwiseNot(channels[i], c); channels[i + channelCount] = c; } var regionVecs = new VectorOfERStat[channels.Length]; for (int i = 0; i < regionVecs.Length; i++) { regionVecs[i] = new VectorOfERStat(); } try { for (int i = 0; i < channels.Length; i++) { er1.Run(channels[i], regionVecs[i]); er2.Run(channels[i], regionVecs[i]); } using (var vm = new VectorOfUMat(channels)) { regions = ERFilter.ERGrouping(image, vm, regionVecs, ERFilter.GroupingMethod.OrientationHoriz, "Assets\\trained_classifier_erGrouping.xml", 0.5f); } } finally { foreach (UMat tmp in channels) { if (tmp != null) { tmp.Dispose(); } } foreach (VectorOfERStat tmp in regionVecs) { if (tmp != null) { tmp.Dispose(); } } } Rectangle imageRegion = new Rectangle(Point.Empty, image.Size); for (int i = 0; i < regions.Length; i++) { Rectangle r = ScaleRectangle(regions[i], 1.1); r.Intersect(imageRegion); regions[i] = r; } } var allChars = new List <Tesseract.Character>(); String allText = String.Empty; foreach (Rectangle rect in regions) { using (Mat region = new Mat(image, rect)) { _ocr.SetImage(region); if (_ocr.Recognize() != 0) { return(null); } //var characters = _ocr.GetCharacters(); ////convert the coordinates from the local region to global //for (int i = 0; i < characters.Length; i++) { // Rectangle charRegion = characters[i].Region; // charRegion.Offset(rect.Location); // characters[i].Region = charRegion; //} //allChars.AddRange(characters); allText += _ocr.GetUTF8Text() + "|"; } } //Bgr drawRegionColor = new Bgr(Color.Red); //foreach (Rectangle rect in regions) { // CvInvoke.Rectangle(image, rect, drawRegionColor.MCvScalar); //} //foreach (Tesseract.Character c in allChars) { // CvInvoke.Rectangle(image, c.Region, drawCharColor.MCvScalar); //} return(allText); } }