Fourier Transform in EmguCV 3.4.1 - c#

The following code doesn't compile in EmguCV 3.4.1.
Image<Gray, float> image = new Image<Gray, float>(path);
IntPtr complexImage = CvInvoke.cvCreateImage(image.Size,
Emgu.CV.CvEnum.IplDepth.IplDepth32F, 2);
CvInvoke.cvSetZero(complexImage); // Initialize all elements to Zero
CvInvoke.cvSetImageCOI(complexImage, 1);
CvInvoke.cvCopy(image, complexImage, IntPtr.Zero);
CvInvoke.cvSetImageCOI(complexImage, 0);
Matrix<float> dft = new Matrix<float>(image.Rows, image.Cols, 2);
CvInvoke.cvDFT(complexImage, dft, Emgu.CV.CvEnum.DxtType.Forward, 0);
//The Real part of the Fourier Transform
Matrix<float> outReal = new Matrix<float>(image.Size);
//The imaginary part of the Fourier Transform
Matrix<float> outIm = new Matrix<float>(image.Size);
CvInvoke.cvSplit(dft, outReal, outIm, IntPtr.Zero, IntPtr.Zero);
//Show The Data
CvInvoke.cvShowImage("Real", outReal);
CvInvoke.cvShowImage("Imaginary ", outIm);
Some functions
cvSetZero()
cvDFT()
cvShowImage()
are not available in this version of EmguCV.
How can I get around this issue?

Since version 3.0 EmguCV goes more for Mat instead of Image. Also somemethods were moved from CvInvoke to Mat or Image or were renamed (example: CvInvoke.cvShowImage --> CvInvoke.Imshow).
I also had this problem with dft and tried to port the code from the openCV example to c#. This is what I work with (using EmguCV 3.4.1):
var image = new Mat(path, ImreadModes.Grayscale);
int a = CvInvoke.GetOptimalDFTSize(image.Rows);
int b = CvInvoke.GetOptimalDFTSize(image.Cols);
var extended = new Mat();
CvInvoke.CopyMakeBorder(image, extended, 0, a - image.Rows, 0, b - image.Cols, BorderType.Constant, new MCvScalar(0));
extended.ConvertTo(extended, DepthType.Cv32F);
var vec = new VectorOfMat(extended, new Mat(extended.Size, DepthType.Cv32F, 1));
var complex = new Mat();
CvInvoke.Merge(vec, complex);
CvInvoke.Dft(complex, complex, DxtType.Forward, 0);
CvInvoke.Split(complex, vec);
vec[0].ConvertTo(vec[0], DepthType.Cv8U);
vec[1].ConvertTo(vec[1], DepthType.Cv8U);
CvInvoke.Imshow("Real", vec[0]);
CvInvoke.Imshow("Img", vec[1]);

Some methods have been renamed or moved. Use CvInvoke.Dft with Image.toUMat and UMat for the image manipulation. ImageViewer can be used for displaying images.
Image<Gray, float> image = new Image<Gray, float>(path);
UMat dftImage = new UMat(image.Size, Emgu.CV.CvEnum.DepthType.Cv32F, 2);
CvInvoke.Dft(image, dftImage, Emgu.CV.CvEnum.DxtType.Forward, image.Rows);

Related

Emgu.CV.OCR not recognize a clear image. What could I do with the image to improve recognition?

I'm trying to recognize a text in an image. I'm using Emgu.CV in C#.
I think the image is clear enough to get the text but I don't get 100%.(Attached two images
)
Can I do something with the image to obtain a better result?
I have used "eng" too but the result is the same.
Emgu.CV.OCR.Tesseract _ocr=new Emgu.CV.OCR.Tesseract(#"./tessdata", "spa", OcrEngineMode.Default);
Emgu.CV.Image<Bgr, Byte> original = new Emgu.CV.Image<Bgr, Byte>(fi.FullName);
Rectangle rec = new Rectangle(105, 132, 50, 25);
original.ROI = rec;
Emgu.CV.Image<Bgr, Byte> crop = new Emgu.CV.Image<Bgr, Byte>(original.Width, original.Height);
CvInvoke.cvCopy(original, crop, IntPtr.Zero);
CvInvoke.Normalize(crop, crop, 0, 255, NormType.MinMax, DepthType.Default);
Emgu.CV.OCR.Pix pix = new Emgu.CV.OCR.Pix(crop.Mat);
_ocr.SetImage(pix);
_ocr.Recognize();
var words = _ocr.GetCharacters();
Get "AS000"
Get "AO800"
I try this
Emgu.CV.OCR.Tesseract _ocr = new
Emgu.CV.OCR.Tesseract(#"./tessdata", "spa", OcrEngineMode.LstmOnly);
_ocr.SetVariable("tessedit_char_whitelist","abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
_ocr.SetVariable("tessedit_pageseg_mode", "6");
Emgu.CV.Image<Bgr, Byte> original = new Emgu.CV.Image<Bgr, Byte>(fi.FullName);
Rectangle rec = new Rectangle(105, 132, 100, 25);
original.ROI = rec;
Emgu.CV.Image<Bgr, Byte> crop = new Emgu.CV.Image<Bgr, Byte>(original.Width, original.Height);
CvInvoke.cvCopy(original, crop, IntPtr.Zero);
Mat gray = new Mat();
gray = crop.Mat;
CvInvoke.CvtColor(crop, crop, ColorConversion.Bgr2Gray);
CvInvoke.Resize(crop, crop, new Size(crop.Cols*10, crop.Rows*10)); //for DPI
CvInvoke.Threshold(crop, crop, 0, 255, ThresholdType.Binary | ThresholdType.Otsu); //for Binarize
CvInvoke.GaussianBlur(crop, crop, new Size(1, 1), 0);
Emgu.CV.OCR.Pix pix = new Emgu.CV.OCR.Pix(crop.Mat);
_ocr.SetImage(pix);
_ocr.Recognize();
The result is better but not 100%.

How to get rid of unnecessary lines with emgu cv

I'm trying to detect contour of an ellipse-like water droplet with Emgu CV. I wrote code for contour detection:
public List<int> GetDiameters()
{
string inputFile = #"path.jpg";
Image<Bgr, byte> imageInput = new Image<Bgr, byte>(inputFile);
Image<Gray, byte> grayImage = imageInput.Convert<Gray, byte>();
Image<Gray, byte> bluredImage = grayImage;
CvInvoke.MedianBlur(grayImage, bluredImage, 9);
Image<Gray, byte> edgedImage = bluredImage;
CvInvoke.Canny(bluredImage, edgedImage, 50, 5);
Image<Gray, byte> closedImage = edgedImage;
Mat kernel = CvInvoke.GetStructuringElement(Emgu.CV.CvEnum.ElementShape.Ellipse, new System.Drawing.Size { Height = 100, Width = 250}, new System.Drawing.Point(-1, -1));
CvInvoke.MorphologyEx(edgedImage, closedImage, Emgu.CV.CvEnum.MorphOp.Close, kernel, new System.Drawing.Point(-1, -1), 0, Emgu.CV.CvEnum.BorderType.Replicate, new MCvScalar());
System.Drawing.Point(100, 250), 10000, Emgu.CV.CvEnum.BorderType.Default, new MCvScalar()
Image<Gray, byte> contoursImage = closedImage;
Image<Bgr, byte> imageOut = imageInput;
VectorOfVectorOfPoint rescontours1 = new VectorOfVectorOfPoint();
using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
{
CvInvoke.FindContours(contoursImage, contours, null, Emgu.CV.CvEnum.RetrType.List,
Emgu.CV.CvEnum.ChainApproxMethod.LinkRuns);
MCvScalar color = new MCvScalar(0, 0, 255);
int count = contours.Size;
for (int i = 0; i < count; i++)
{
using (VectorOfPoint contour = contours[i])
using (VectorOfPoint approxContour = new VectorOfPoint())
{
CvInvoke.ApproxPolyDP(contour, approxContour,
0.01 * CvInvoke.ArcLength(contour, true), true);
var area = CvInvoke.ContourArea(contour);
if (area > 0 && approxContour.Size > 10)
{
rescontours1.Push(approxContour);
}
CvInvoke.DrawContours(imageOut, rescontours1, -1, color, 2);
}
}
}
}
result so far:
I think there is a problem with approximation. How to get rid of internal lines and close external contour?
I might need some more information to exactly pinpoint your issue, but it might be something to do with your median blur. I would see if you are blurring enough that EmguCV things the blur is enough that you can canny edge detection. Another method that you could use is Dilate. Try Dialating your Canny edge detection and see if you get any better results.
EDIT
Here is the code below
public List<int> GetDiameters()
{
//List to hold output diameters
List<int> diametors = new List<int>();
//File path to where the image is located
string inputFile = #"C:\Users\jones\Desktop\Image Folder\water.JPG";
//Read in the image and store it as a mat object
Mat img = CvInvoke.Imread(inputFile, Emgu.CV.CvEnum.ImreadModes.AnyColor);
//Mat object that will hold the output of the gaussian blur
Mat gaussianBlur = new Mat();
//Blur the image
CvInvoke.GaussianBlur(img, gaussianBlur, new System.Drawing.Size(21, 21), 20, 20, Emgu.CV.CvEnum.BorderType.Default);
//Mat object that will hold the output of the canny
Mat canny = new Mat();
//Canny the image
CvInvoke.Canny(gaussianBlur, canny, 40, 40);
//Mat object that will hold the output of the dilate
Mat dilate = new Mat();
//Dilate the canny image
CvInvoke.Dilate(canny, dilate, null, new System.Drawing.Point(-1, -1), 6, Emgu.CV.CvEnum.BorderType.Default, new MCvScalar(0, 0, 0));
//Vector that will hold all found contours
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
//Find the contours and draw them on the image
CvInvoke.FindContours(dilate, contours, null, Emgu.CV.CvEnum.RetrType.External, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);
CvInvoke.DrawContours(img, contours, -1, new MCvScalar(255, 0, 0), 5, Emgu.CV.CvEnum.LineType.FourConnected);
//Variables to hold relevent info on what is the biggest contour
int biggest = 0;
int index = 0;
//Find the biggest contour
for (int i = 0; i < contours.Size; i++)
{
if (contours.Size > biggest)
{
biggest = contours.Size;
index = i;
}
}
//Once all contours have been looped over, add the biggest contour's index to the list
diametors.Add(index);
//Return the list
return diametors;
}
The first thing you do is blur the image.
Then you canny the image.
Then you dilate the image, as to make the final output contours more uniform.
Then you just find contours.
I know the final contours are a little bigger than the water droplet, but this is the best that I could come up with. You can probably fiddle around with some of the settings and the code above to make the result a little cleaner.

How to merge two images using OpenCvSharp4 v4.2

I need to create a method in C# that will receive an image (or path to it), blur it and then try to merge the blurred image with the original using OpenCvSharp4. So far, I can create the blur image just fine, but the merging part is giving me a hard time. I've had tried a few pieces of sample code found online to no avail. Any idea how to get the merging part ?
-thanks,
var mat = Cv2.ImRead(OriginalFileName, ImreadModes.Unchanged);
Cv2.Resize(mat, mat, new Size(933, 934), 0d, 0d, InterpolationFlags.Linear);
Cv2.CvtColor(mat, mat, ColorConversionCodes.BGR2RGB);
Mat newImage = new Mat();
Cv2.GaussianBlur(mat, newImage, new Size(67, 67), 0d, 0d, BorderTypes.Default);
Cv2.CvtColor(newImage, newImage, ColorConversionCodes.BGR2RGB);
Mat merged = Mat.Ones || Mat.Zeros // HELP NEEDED HERE
Cv2.Merge(new Mat[] { mat, newImage }, merged);
Found a good hint and sample code here: How to merge two images in opencv?
Here's my final solution:
var mat = Cv2.ImRead(OriginalFileName, ImreadModes.Unchanged);
Cv2.Resize(mat, mat, new Size(933, 934), 0d, 0d, InterpolationFlags.Linear);
Cv2.CvtColor(mat, mat, ColorConversionCodes.BGR2RGB);
Mat newImage = new Mat();
Cv2.GaussianBlur(mat, newImage, new Size(67, 67), 0d, 0d, BorderTypes.Default);
Cv2.CvtColor(newImage, newImage, ColorConversionCodes.BGR2RGB);
//merging
double alpha = 0; double beta;
Mat src1, src2, merge;
merge = new Mat();
src1 = mat;
src2 = newImage;
beta = (1.0 - alpha);
Cv2.AddWeighted(src1, alpha, src2, beta, 0.0, merge);

What is the minimal code to find the Fourier transform of an image in EmguCV.3.1.0.1?

I want to find the FT of an image, and show its magnitude, and, phase spectrum in EmguCV.3.1.0.1.
I was trying something like the following:
public partial class Form1 : Form
{
const string path = #"lenagr.png";
Image<Bgr, float> image;
public Form1()
{
InitializeComponent();
image = new Image<Bgr, float>(path);
pictureBox1.Image = image.Bitmap;
}
private void button1_Click(object sender, EventArgs e)
{
Mat dft = new Mat(image.Size, DepthType.Default, 2);
CvInvoke.Dft(image, dft, DxtType.Forward, image.Rows);
Mat[] images = dft.Split();
//Show The Data
//Image<Bgr, float> im2 = dft.ToImage<Bgr, float>();
pictureBox2.Image = images[0].Bitmap;
}
}
This source code freezes the application.
So, What is the absolutely minimal code to find the Fourier transform of an image in EmguCV.3.1.0.1?
Note: The following source code doesn't even compile in EmguCV.3.1.0.1. And, it looks a job lot.
Image<Gray, float> image = new Image<Gray, float>(open.FileName);
IntPtr complexImage = CvInvoke.cvCreateImage(image.Size, Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_32F, 2);
CvInvoke.cvSetZero(complexImage); // Initialize all elements to Zero
CvInvoke.cvSetImageCOI(complexImage, 1);
CvInvoke.cvCopy(image, complexImage, IntPtr.Zero);
CvInvoke.cvSetImageCOI(complexImage, 0);
Matrix<float> dft = new Matrix<float>(image.Rows, image.Cols, 2);
CvInvoke.cvDFT(complexImage, dft, Emgu.CV.CvEnum.CV_DXT.CV_DXT_FORWARD, 0);
//The Real part of the Fourier Transform
Matrix<float> outReal = new Matrix<float>(image.Size);
//The imaginary part of the Fourier Transform
Matrix<float> outIm = new Matrix<float>(image.Size);
CvInvoke.cvSplit(dft, outReal, outIm, IntPtr.Zero, IntPtr.Zero);
//Show The Data
CvInvoke.cvShowImage("Real", outReal);
CvInvoke.cvShowImage("Imaginary ", outIm);
It is not clear what statement is doing what. Also, it mixes up IntPtr, Image<T1, T2>, Matrix<T>, and doesn't make use of Mat.

direct and inverse fourier transform in EMGU CV

I'm doing a small experiment using fourier transform on emgu cv. My aim is to have the fourier transform of an image, then take the inverse fourier transform again, and check if the image shows up or not. mathematically, it should.
this is my code which i believe is correct
Image<Gray, float> image = new Image<Gray, float>("c://box1.png");
IntPtr complexImage = CvInvoke.cvCreateImage(image.Size, Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_32F, 2);
CvInvoke.cvSetZero(complexImage); // Initialize all elements to Zero
CvInvoke.cvSetImageCOI(complexImage, 1);
CvInvoke.cvCopy(image, complexImage, IntPtr.Zero);
CvInvoke.cvSetImageCOI(complexImage, 0);
Matrix<float> dft = new Matrix<float>(image.Rows, image.Cols, 2);
CvInvoke.cvDFT(complexImage, dft, Emgu.CV.CvEnum.CV_DXT.CV_DXT_FORWARD, 0);
Matrix<float> idft = new Matrix<float>(dft.Rows, dft.Cols, 2);
CvInvoke.cvDFT(dft, idft, Emgu.CV.CvEnum.CV_DXT.CV_DXT_INVERSE, 0);
IntPtr complexImage2 = CvInvoke.cvCreateImage(idft.Size, Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, 2);
CvInvoke.cvShowImage("picture", idft);
System.Threading.Thread.Sleep(99999); // to wait and see the picture
I have two problems:
1- error : an error shows up saying " OpenCV: Source image must have 1, 3 or 4 channels " i believe its related about the IDFT, but I couldn't solve it
2- it still shows an output image, but unfortunately, its not the original image that was input. all what show is a plain grey image.
Thanks.
Try this,
Image<Gray, System.Single> _image = new Image<Gray, System.Single>("c://box1.png");
Image<Gray, System.Single> DFTimage = new Image<Gray, System.Single>(_image.Size);
Image<Gray, System.Single> Original = new Image<Gray, System.Single>(_image.Size);
CvInvoke.cvDFT(_image.Ptr, DFTimage.Ptr,Emgu.CV.CvEnum.CV_DXT.CV_DXT_FORWARD, -1);
CvInvoke.cvDFT(DFTimage.Ptr, Original.Ptr,Emgu.CV.CvEnum.CV_DXT.CV_DXT_INVERSE, -1);
CvInvoke.cvShowImage("picture", Original);

Categories

Resources