Emgucv Image to LoadRawTextureData - c#

I need help for converting Emgucv videoCapture image to LoadRawTextureData of unity to display images/videos in Unity3d 2018.1.
I am able to display images but it show strange lines and distorted image effects or some kind of shuttering/scattering.
I read the question in this post and apply the solution but the problem is not solved Convert Mat to Texture2d(Stackoverflow)
I think the Colorspace of Emgucv image did not matched with the texture2d.
Code:
void Start () {
vc = new VideoCapture(0);
vc.FlipVertical = true; //The image I am getting from webcam is flipped
myMaterial = GetComponent<Renderer>().material;
frameHeight = (int)vc.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameHeight);
frameWidth = (int)vc.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameWidth);
camera = new Texture2D(frameHeight,frameWidth, TextureFormat.RGB24, false,false);
}
I am getting images in this part of code and converting the color space as per texture2d format.
void Update () {
Mat secondimage = new Mat();
Mat myimage = vc.QueryFrame();
CvInvoke.CvtColor(myimage, secondimage, Emgu.CV.CvEnum.ColorConversion.Bgr2Rgb);
Image<Rgb, byte> hello = secondimage.ToImage<Rgb, byte>();
camera.LoadRawTextureData(hello.bytes);
camera.Apply();
myMaterial.mainTexture = camera;
}
Results:
The Result is kind of strange,take a look on following result images.
This is my hand holding in Front of camera.This image is orignal texture2d image.
Image1
This image is displayed on the 3d plane in unity3d.
Image2
As code explain i already Convert image Bgr2Rgb.
update:
I simply exchange the width and height in texture2d and wow it worked.
camera = new Texture2D(frameWidth, frameHeight, TextureFormat.RGB24,false,false);

Related

Copy smaller Mat to larger Mat OpenCv For Unity

I'm trying to take a smaller image mat and copy it into larger mat so I can resize it while keeping the aspect ratio of the image. So, basically this:
So far, this is the code I've written:
private Mat MakeMatFrame(Texture2D image)
{
// Texture must be of right input size
Mat img_mat = new Mat(image.height, image.width, CvType.CV_8UC4, new Scalar(0, 0, 0, 255));
texture2DToMat(image, img_mat);
return img_mat;
}
private void letterBoxImage(Texture2D image)
{
// Get input image as a mat
Mat source = MakeMatFrame(image);
// Create the mat that the source will be put in
int col = source.cols();
int row = source.rows();
int _max = Math.Max(col, row);
Mat resized = Mat.zeros(_max, _max, CvType.CV_8UC4);
// Fill resized
Mat roi = new Mat(resized, new Rect(0, 0, col, row));
source.copyTo(roi);
Texture2D tex2d = new Texture2D(resized.cols(), resized.rows());
matToTexture2D(resized, tex2d);
rawImage.texture = tex2d;
}
Everything I've looked at tells me this is the right approach to take (get a region of interest, fill it in). But instead of getting that third image with the children above the gray region, I just have a gray region.
In other words, the image isn't copying over properly. I've trying using a submat as well, but it failed miserably.
I've been looking for C# code on how to do this sort of thing with OpenCv For Unity, but I can only find C++ code. Which tells me to do exactly this.
Is there some sort of "apply changes" function I'm unaware of for Mats? Am I selecting the region of interest incorrectly? Or is it something else?
sorry for my english,but ur code has a bug.
Mat roi = new Mat(resized, new Rect(0, 0, col, row));
image copied to roi,but this mat not related with resized Mat.so u have to do like this:
Rect roi=new Rect(0,0,width,height);
source.copyto(resized.submat(roi));

how to crop image with polygon in c#

I'm making a labeling tool.
Goal :By drawing a polygon on the picture, you have to export the image ​​inside the polygon to the outside.
example
extract
This is what I drew in the my program.
But I don't know how to extract this region. I want to know how to extract this area.
I have saved the vertices of the picture above in an object. But I don't know how to extract data from the image through these vertices
========================================
So I found this.
https://www.codeproject.com/Articles/703519/Cropping-Particular-Region-In-Image-Using-Csharp
but it is not work
Can't convert Bitmap to IplImage
It doesn't work for the same reason.
In the post, I am going to use opencvsharp 4.x, but the program I am fixing now is .netframework 3.5, so it does not support opencvsharp 4.x.
What should I do?
============================
I made a function referring to the answer, but it doesn't work...
I want to know why.
void CropImage(Bitmap bitmap, Point[] points)
{
Rectangle rect = PaddingImage(points, bitmap);
TextureBrush textureBrush = new TextureBrush(bitmap);
Bitmap bmp1 = new Bitmap(rect.Width, rect.Height);
using (Graphics g = Graphics.FromImage(bmp1))
{
g.FillPolygon(textureBrush, points);
}
string ima_path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
bmp1.Save(ima_path + "\\Image.png", ImageFormat.Png);
}
extract Image
original
If you use a small polygon, there is no output at all.
You will notice that the two images are slightly different.
It seems to me that the part where the center point is cut and extracted is different. I don't know if what I was thinking is correct.
You would create a new bitmap, at least as large as the bounding box of your polygon. Create a graphics object from this new bitmap. You can then draw the polygon to this bitmap, using the original image as a texture brush. Note that you might need to apply transform matrix to translate from the full image coordinates to the cropped image coordinates.
Note that it looks like you have radiological images. These are typically 16 bit images, so they will need to be converted to 8bit mono, or 24bit RGB before they can be used. This should already be done in the drawing code if you have access to the source. Or you can do it yourself.
this works for me
private Bitmap CropImage(Bitmap bitmap, List<Point> points)
{
int pminx = 9999, pminy = 9999, pmaxx = 0, pmaxy = 0; System.Drawing.Point[] pcol = new System.Drawing.Point[points.Count]; int i = 0;
foreach (Point pc in points)
{
if (pc.X > pmaxx) pmaxx = (int)pc.X;
if (pc.Y > pmaxy) pmaxy = (int)pc.Y;
if (pc.X < pminx) pminx = (int)pc.X;
if (pc.Y < pminy) pminy = (int)pc.Y;
pcol[i] = new System.Drawing.Point((int)pc.X, (int)pc.Y);
i++;
}
TextureBrush textureBrush = new TextureBrush(bitmap);
Bitmap bmpWrk = new Bitmap(bitmap.Width, bitmap.Height);
using (Graphics g = Graphics.FromImage(bmpWrk))
{
g.FillPolygon(textureBrush, pcol);
}
System.Drawing.Rectangle CropRect = new System.Drawing.Rectangle(pminx, pminy, pmaxx - pminx, pmaxy - pminy);
return bmpWrk.Clone(CropRect, bmpWrk.PixelFormat);
}

C# deskew colored image with Accord framework

I am using the accord framework to deskew an image that I loaded into a bitmap. Now the problem I keep having is that I want to deskew an image that contains color but every time I try to deskew it, it keeps asking for a greyscaled image. Now using graphics I am able to convert it to a 8bpp greyscaled pixelformat so I'm able to deskew it but I don't need the greyscaled corrected image, I need the colored one.
Is there any possible way to do this with the accord framework?
This is the code i'm currently using.
public Bitmap DeskewImage(Bitmap bmp)
{
DocumentSkewChecker sc = new DocumentSkewChecker();
Bitmap workmap = new Bitmap(bmp);
Bitmap workmap1 = new Bitmap(bmp);
Bitmap tempWorkmap = new Bitmap(workmap.Width, workmap.Height);
using (Graphics g = Graphics.FromImage(tempWorkmap))
g.DrawImage(workmap, 0, 0);
Grayscale filter = new Grayscale(0.2125, 0.7154, 0.0721);
workmap = filter.Apply(tempWorkmap);
double angle = sc.GetSkewAngle(workmap);
RotateBilinear rf = new RotateBilinear(-angle);
rf.FillColor = Color.White;
workmap1 = rf.Apply(workmap);
return workmap1;
}

Xamarin.iOS Image on Image Watermark

How can I add a png image as a watermark to a larger image using Xamarin.iOS c# and save the output to the device?
I figured out the Xamarin.Android version from another question posted here.
Thanks in Advance!!
Using an image context, you can draw the original, then the watermark at the necessary location and obtain a new image from the context.
ImageContext example:
var originalImage = UIImage.FromBundle("buymore.jpg");
var watermarkImage = UIImage.FromFile("vs.png");
UIGraphics.BeginImageContextWithOptions(originalImage.Size, true, 1.0f);
originalImage.Draw(CGPoint.Empty);
watermarkImage.Draw(new CGRect(new CGPoint(200, 200), watermarkImage.Size));
var processedImage = UIGraphics.GetImageFromCurrentImageContext();
If your original and watermark images are the same size, you can use a CIFilter (CISourceOverCompositing) to "overlay" one image on top of another (assuming your watermark has a white or alpha background. This is my preferred method due to the speed.
CISourceOverCompositing example:
UIImage processedimage;
using (var filter = new CISourceOverCompositing())
{
filter.Image = new CIImage(UIImage.FromBundle("vs.png"));
filter.BackgroundImage = new CIImage(UIImage.FromBundle("buymore.jpg"));
processedimage = UIImage.FromImage(filter.OutputImage);
}

Black line at bottom of WebCamTexture image

When getting video input from a webcam via WebCamTexture the bottom row of the returned image is completely black (RGB = 0,0,0).
I have tried several different webcams and get the same result with all of them.
I do get a correct image when using the Windows 10 Camera app and also when getting a webcam feed in Processing or Java.
The black line (always 1 pixel high and as wide as the image) appears when showing video on the canvas, saving a snapshot to disk and also when looking directly at the pixel data with GetPixels32().
Here is the black-line at the Bottom of the picture image:
I have confirmed that the image returned is the correct size, i.e. the black row is not an extra row. It's always the lowest line of the image that is black.
I have included the c# code I'm using below.
What is the cause of this black line and is there a way to avoid it?
I have looked for any information on this issue but not found anything online. I'm a complete beginner at Unity and would be grateful for any help.
I'm using Unity version 5.6.2 but had the same issue with 5.5
public class CamController : MonoBehaviour
{
private WebCamTexture webcamTexture;
private WebCamDevice[] devices;
void Start()
{
//start webcam
webcamTexture = new WebCamTexture();
devices = WebCamTexture.devices;
webcamTexture.deviceName = devices[0].name;
webcamTexture.Play();
}
void Update()
{
//if user presses C capture cam image
if (Input.GetKeyDown(KeyCode.C))
captureImage();
}
void captureImage()
{
//get webcam pixels
Color32[] camPixels;
camPixels = webcamTexture.GetPixels32();
//print pixel data for first and second (from bottom) lines of image to console
for (int y = 0; y < 2; y++)
{
Debug.Log("Line: " + y);
for (int x = 0; x < webcamTexture.width; x++)
{
Debug.Log(x + " - " + camPixels[y * webcamTexture.width + x]);
}
}
//save webcam image as png
Texture2D brightBGTexture = new Texture2D(webcamTexture.width, webcamTexture.height);
brightBGTexture.SetPixels32(camPixels, 0);
brightBGTexture.Apply();
byte[] pngBytes = brightBGTexture.EncodeToPNG();
File.WriteAllBytes(Application.dataPath + "/../camImage.png", pngBytes);
}
}
After calling SetPixels32, you must call Texture2D.Apply to apply the changes to the Texture2D.
You should that before encoding the Texture2D to png.
//save webcam image as png
Texture2D brightBGTexture = new Texture2D(webcamTexture.width, webcamTexture.height);
brightBGTexture.SetPixels32(camPixels, 0);
brightBGTexture.Apply();
byte[] pngBytes = brightBGTexture.EncodeToPNG();
File.WriteAllBytes(Application.dataPath + "/../camImage.png", pngBytes);
EDIT:
Even with calling Texture2D.Apply() the problem is still there. This is a bug with the WebCamTexture API and you should file for a bug report through the Editor.

Categories