Add two sub-images into one new image using emgu cv - c#

I have two images with different dimensions and I want to create another large image includes them vertically.
private Image<Gray, Byte> newImage(Image<Gray, Byte> image1, Image<Gray, Byte> image2)
{
int ImageWidth = 0;
int ImageHeight = 0;
//get max width
if (image1.Width > image2.Width)
ImageWidth = image1.Width;
else
ImageWidth = image2.Width;
//calculate new height
ImageHeight = image1.Height + image2.Height;
//declare new image (large image).
Image<Gray, Byte> imageResult = new Image<Gray, Byte>(ImageWidth, ImageHeight);
imageResult.ROI = new Rectangle(0, 0, image1.Width, image1.Height);
image1.CopyTo(imageResult);
imageResult.ROI = new Rectangle(0, image1.Height, image2.Width, image2.Height);
image2.CopyTo(imageResult);
return imageResult;
}
The returned image is a black image and doesn't contain the two images, please help me where's the problem?
Thanks.

Your approach was correct. You simply had to remove the ROI. Just add at the end:
imageResult.ROI = Rectangle.Empty;
The Final Result shoul look like this:
imageResult.ROI = new Rectangle(0, 0, image1.Width, image1.Height);
image1.CopyTo(imageResult);
imageResult.ROI = new Rectangle(0, image1.Height, image2.Width, image2.Height);
image2.CopyTo(imageResult);
imageResult.ROI = Rectangle.Empty;

The solution in the following:
private Image<Gray, Byte> newImage(Image<Gray, Byte> image1, Image<Gray, Byte> image2)
{
int ImageWidth = 0;
int ImageHeight = 0;
//get max width
if (image1.Width > image2.Width)
ImageWidth = image1.Width;
else
ImageWidth = image2.Width;
//calculate new height
ImageHeight = image1.Height + image2.Height;
//declare new image (large image).
Image<Gray, Byte> imageResult;
Bitmap bitmap = new Bitmap(Math.Max(image1.Width , image2.Width), image1.Height + image2.Height);
using (Graphics g = Graphics.FromImage(bitmap))
{
g.DrawImage(image1.Bitmap, 0, 0);
g.DrawImage(image2.Bitmap, 0, image1.Height);
}
imageResult = new Image<Gray, byte>(bitmap);
return imageResult;
}

Related

Is it possible to create a qr code using ZXing.Net without a quiet zone?

(How) is it possible to create a qr code using ZXing.Net without a quiet zone?
This is my current code:
BarcodeWriter barcodeWriter = new BarcodeWriter();
barcodeWriter.Format = BarcodeFormat.QR_CODE;
barcodeWriter.Renderer = new BitmapRenderer();
EncodingOptions encodingOptions = new EncodingOptions();
encodingOptions.Width = 500;
encodingOptions.Height = 500;
encodingOptions.Margin = 0;
encodingOptions.Hints.Add(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
barcodeWriter.Options = encodingOptions;
bitmap = barcodeWriter.Write(compressedText);
Thanks!
ZXing.Net doesn't support image scaling with anti-aliasing. That means it can only resize by integer values. In your case you should create the smallest possible image and resize the resulting image with an image manipulation library or the Bitmap and Graphics classes from the framework.
var barcodeWriter = new BarcodeWriter
{
Format = BarcodeFormat.QR_CODE
};
// set width and height to 1 to get the smallest possible representation without a quiet zone around the qr code
var encodingOptions = new EncodingOptions
{
Width = 1,
Height = 1,
Margin = 0
};
encodingOptions.Hints.Add(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
barcodeWriter.Options = encodingOptions;
var bitmap = barcodeWriter.Write(compressedText);
// scale the image to the desired size
var scaledBitmap = ScaleImage(bitmap, 500, 500);
private static Bitmap ScaleImage(Bitmap bmp, int maxWidth, int maxHeight)
{
var ratioX = (double)maxWidth / bmp.Width;
var ratioY = (double)maxHeight / bmp.Height;
var ratio = Math.Min(ratioX, ratioY);
var newWidth = (int)(bmp.Width * ratio);
var newHeight = (int)(bmp.Height * ratio);
var newImage = new Bitmap(newWidth, newHeight, PixelFormat.Format24bppRgb);
using (var graphics = Graphics.FromImage(newImage))
{
graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.DrawImage(bmp, 0, 0, newWidth, newHeight);
}
return newImage;
}

Emgu CV Image sharpening and controur detection

I am working on a project where I need to identify dots from IR lasers on a surface. I use for that a camera with IR filter
Some input images:
There can be several dots, too. So I tried to sharpen this image from webcam and then use FindContours method of Emgu CV.
There is my code:
public static Image<Gray, byte> Sharpen(Image<Gray, byte> image, int w, int h, double sigma1, double sigma2, int k)
{
w = (w % 2 == 0) ? w - 1 : w;
h = (h % 2 == 0) ? h - 1 : h;
//apply gaussian smoothing using w, h and sigma
var gaussianSmooth = image.SmoothGaussian(w, h, sigma1, sigma2);
//obtain the mask by subtracting the gaussian smoothed image from the original one
var mask = image - gaussianSmooth;
//add a weighted value k to the obtained mask
mask *= k;
//sum with the original image
image += mask;
return image;
}
private void ProcessFrame(object sender, EventArgs arg)
{
Mat frame = new Mat();
if (_capture.Retrieve(frame, CameraDevice))
{
Image<Bgr, byte> original = frame.ToImage<Bgr, byte>();
Image<Gray, byte> img = Sharpen(frame.ToImage<Gray, byte>(), 100, 100, 100, 100, 30);
Image<Gray, byte> thresh = new Image<Gray, byte>(img.Size);
CvInvoke.PyrDown(img, thresh);
CvInvoke.PyrUp(thresh, thresh);
Image<Gray, byte> mask = new Image<Gray, byte>(thresh.Size);
Image<Gray, byte> cannyImg = thresh.Canny(10, 50);
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
Mat hierarchy = new Mat();
CvInvoke.FindContours(
cannyImg,
contours,
hierarchy,
RetrType.External,
ChainApproxMethod.ChainApproxSimple
);
Image<Bgr, byte> resultImage = img.Copy().Convert<Bgr, byte>();
int contCount = contours.Size;
for (int i = 0; i < contCount; i++)
{
using (VectorOfPoint contour = contours[i])
{
resultImage.Draw(CvInvoke.BoundingRectangle(contour), new Bgr(255, 0, 0), 5);
}
}
captureBox.Image = original.Bitmap;
cvBox.Image = resultImage.Bitmap;
}
}
Example of result image:
So it almost all the time works as I expect it to, but framerate is very low. I'm getting like 10-15 fps with resolution of 640x480. I need to be able to do the same thing for 1920x1080 with at least 30 fps. It's my first time with OpenCV and Emgu.CV. What can I do to make it perform better?
I solved this just setting the threshold, so that image turns black and white only. By adjusting the threshold I was able to achieve the same results if not better in terms of clarity, but also performance drastically improved since there is not heavy processing going on
Here is a snippet with ARCore library instead on EmguCV
var bitmap = eventArgs.Frame;
var filter = new Grayscale(0.2125, 0.7154, 0.0721);
var grayImage = filter.Apply(bitmap);
var thresholdFilter = new Threshold(CurrentThreshold);
thresholdFilter.ApplyInPlace(grayImage);
var blobCounter = new BlobCounter();
blobCounter.ProcessImage(grayImage);
var rectangles = blobCounter.GetObjectsRectangles();

Finding contour points in emgucv

I am working with emguCV for finding contours essential points then saving this point in a file and user redraw this shape in future. so, my goal is this image:
example
my solution is this:
1. import image to picturebox
2. edge detection with canny algorithm
3. finding contours and save points
I found a lot of points with below codes but i can't drawing first shape with this point!
using Emgu.CV;
using Emgu.Util;
private void button1_Click(object sender, EventArgs e)
{
Bitmap bmp = new Bitmap(pictureBox1.Image);
Image<Bgr, Byte> img = new Image<Bgr, byte>(bmp);
Image<Gray, Byte> gray = img.Convert<Gray, Byte>().PyrDown().PyrUp();
Gray cannyThreshold = new Gray(80);
Gray cannyThresholdLinking = new Gray(120);
Gray circleAccumulatorThreshold = new Gray(120);
Image<Gray, Byte> cannyEdges = gray.Canny(cannyThreshold, cannyThresholdLinking).Not();
Bitmap color;
Bitmap bgray;
IdentifyContours(cannyEdges.Bitmap, 50, true, out bgray, out color);
pictureBox1.Image = color;
}
public void IdentifyContours(Bitmap colorImage, int thresholdValue, bool invert, out Bitmap processedGray, out Bitmap processedColor)
{
Image<Gray, byte> grayImage = new Image<Gray, byte>(colorImage);
Image<Bgr, byte> color = new Image<Bgr, byte>(colorImage);
grayImage = grayImage.ThresholdBinary(new Gray(thresholdValue), new Gray(255));
if (invert)
{
grayImage._Not();
}
using (MemStorage storage = new MemStorage())
{
for (Contour<Point> contours = grayImage.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST, storage); contours != null; contours = contours.HNext)
{
Contour<Point> currentContour = contours.ApproxPoly(contours.Perimeter * 0.015, storage);
if (currentContour.BoundingRectangle.Width > 20)
{
CvInvoke.cvDrawContours(color, contours, new MCvScalar(255), new MCvScalar(255), -1, 1, Emgu.CV.CvEnum.LINE_TYPE.EIGHT_CONNECTED, new Point(0, 0));
color.Draw(currentContour.BoundingRectangle, new Bgr(0, 255, 0), 1);
}
Point[] pts = currentContour.ToArray();
foreach (Point p in pts)
{
//add points to listbox
listBox1.Items.Add(p);
}
}
}
processedColor = color.ToBitmap();
processedGray = grayImage.ToBitmap();
}
In your code you have added contour approximation operation
Contour<Point> currentContour = contours.ApproxPoly(contours.Perimeter * 0.015, storage);
This contour approximation will approximate your Contour to a nearest polygon & so your actual points got shifted. If you want to reproduce the same image you need not to do any approximation.
Refer this thread.

How to change the ColorPalette of an EmguCV image

I'm tying to change the ColorPalette of an EmguCV image, but the Palette does not change!
Sample code:
var img = new Image<Gray, byte>(10, 10);
ColorPalette pal = img.Bitmap.Palette;
pal.Entries[0] = Color.FromArgb(255, 0, 0, 255);
img.Bitmap.Palette = pal;
//img.Bitmap.Palette.Entries[0] != pal.Entries[0];
To me, it seems that the ColorPalette can't be changed. Also, the Entries property only has a getter, no setter.
But if you insist that it is possible to change the ColorPalette, I believe you. So, here's an idea on how to solve it then:
var img = new Image<Gray, byte>(10, 10);
Bitmap bmp = img.Bitmap;
ColorPalette pal = bmp.Palette;
pal.Entries[0] = Color.FromArgb(255, 0, 0, 255);
bmp.Palette = pal;
Image<Gray, byte> changedImage = new Image<Gray, byte>(bmp);
The idea is that you create a new image (or you can replace the old one by img = new Image<Gray, byte>(bmp);) from the Bitmap where you have changed the ColorPalette. I haven't tried it myself, but I think it's worth a try!

Using C# how can I resize a jpeg image?

Using C# how can I resize a jpeg image? A code sample would be great.
I'm using this:
public static void ResizeJpg(string path, int nWidth, int nHeight)
{
using (var result = new Bitmap(nWidth, nHeight))
{
using (var input = new Bitmap(path))
{
using (Graphics g = Graphics.FromImage((System.Drawing.Image)result))
{
g.DrawImage(input, 0, 0, nWidth, nHeight);
}
}
var ici = ImageCodecInfo.GetImageEncoders().FirstOrDefault(ie => ie.MimeType == "image/jpeg");
var eps = new EncoderParameters(1);
eps.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
result.Save(path, ici, eps);
}
}
Good free resize filter and example code.
http://code.google.com/p/zrlabs-yael/
private void MakeResizedImage(string fromFile, string toFile, int maxWidth, int maxHeight)
{
int width;
int height;
using (System.Drawing.Image image = System.Drawing.Image.FromFile(fromFile))
{
DetermineResizeRatio(maxWidth, maxHeight, image.Width, image.Height, out width, out height);
using (System.Drawing.Image thumbnailImage = image.GetThumbnailImage(width, height, new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback), IntPtr.Zero))
{
if (image.Width < thumbnailImage.Width && image.Height < thumbnailImage.Height)
File.Copy(fromFile, toFile);
else
{
ImageCodecInfo ec = GetCodecInfo();
EncoderParameters parms = new EncoderParameters(1);
parms.Param[0] = new EncoderParameter(Encoder.Compression, 40);
ZRLabs.Yael.BasicFilters.ResizeFilter rf = new ZRLabs.Yael.BasicFilters.ResizeFilter();
//rf.KeepAspectRatio = true;
rf.Height = height;
rf.Width = width;
System.Drawing.Image img = rf.ExecuteFilter(System.Drawing.Image.FromFile(fromFile));
img.Save(toFile, ec, parms);
}
}
}
}
C# (or rather: the .NET framework) itself doesn't offer such capability, but it does offer you Bitmap from System.Drawing to easily access the raw pixel data of various picture formats. For the rest, see http://en.wikipedia.org/wiki/Image_scaling
Nice example.
public static Image ResizeImage(Image sourceImage, int maxWidth, int maxHeight)
{
// Determine which ratio is greater, the width or height, and use
// this to calculate the new width and height. Effectually constrains
// the proportions of the resized image to the proportions of the original.
double xRatio = (double)sourceImage.Width / maxWidth;
double yRatio = (double)sourceImage.Height / maxHeight;
double ratioToResizeImage = Math.Max(xRatio, yRatio);
int newWidth = (int)Math.Floor(sourceImage.Width / ratioToResizeImage);
int newHeight = (int)Math.Floor(sourceImage.Height / ratioToResizeImage);
// Create new image canvas -- use maxWidth and maxHeight in this function call if you wish
// to set the exact dimensions of the output image.
Bitmap newImage = new Bitmap(newWidth, newHeight, PixelFormat.Format32bppArgb);
// Render the new image, using a graphic object
using (Graphics newGraphic = Graphics.FromImage(newImage))
{
using (var wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
newGraphic.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
}
// Set the background color to be transparent (can change this to any color)
newGraphic.Clear(Color.Transparent);
// Set the method of scaling to use -- HighQualityBicubic is said to have the best quality
newGraphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
// Apply the transformation onto the new graphic
Rectangle sourceDimensions = new Rectangle(0, 0, sourceImage.Width, sourceImage.Height);
Rectangle destinationDimensions = new Rectangle(0, 0, newWidth, newHeight);
newGraphic.DrawImage(sourceImage, destinationDimensions, sourceDimensions, GraphicsUnit.Pixel);
}
// Image has been modified by all the references to it's related graphic above. Return changes.
return newImage;
}
Source : http://mattmeisinger.com/resize-image-c-sharp
ImageMagick should be the best way. Easy and reliable.
using (var image = new MagickImage(imgfilebuf))
{
image.Resize(len, len);
image.Strip();
using MemoryStream ms = new MemoryStream();
image.Write(ms);
return ms.ToArray();
}

Categories