I want to copy an image from camera to anothe imagebox using ROI. I have searched a lot references about ROI but it still doesn't work. Anybody can help me, please ?
These are what I have done
Image<Bgr, Byte> sourceImage1 = CaptureCam1.QueryFrame();
SourceImageBox.Image = sourceImage1;
ImageCopy = new Image<Bgr, Byte>(Template_Box.Width, Template_Box.Height);
sourceImage1.ROI = new Rectangle(SourceImageBox.Location.X, SourceImageBox.Location.Y, SourceImageBox.Width, SourceImageBox.Height);
sourceImage1.CopyTo(ImageCopy);
Template_Box.Image = ImageCopy;
You should use it like below:
sourceImage1.ROI = new Rectangle(SourceImageBox.Location.X, SourceImageBox.Location.Y, SourceImageBox.Width, SourceImageBox.Height);
Template_Box.Image = sourceImage1.clone();
Related
I am having some issues extracting a blob from an image using EmguCV. Everything I see online uses the Contours object, but I guess that was removed from EmguCV3.0? I get an exception every time I try to use it. I haven't found many recent/relevant SO topics that aren't out of date.
Basically, I have a picture of a leaf. The background might be white, green, black, etc. I want to essentially remove the background so that I can perform operations on the leaf without interference with the background. I'm just not sure where I'm going wrong here:
Image<Bgr, Byte> Original = Core.CurrentLeaf.GetImageBGR;
Image<Gray, Byte> imgBinary = Original.Convert<Gray, Byte>();
imgBinary.PyrDown().PyrUp(); // Smoothen a little bit
imgBinary = imgBinary.ThresholdBinaryInv(new Gray(100), new Gray(255)); // Apply inverse suppression
// Now, copy pixels from original image that are black in the mask, to a new Mat. Then scan?
Image<Gray, Byte> imgMask;
imgMask = imgBinary.Copy(imgBinary);
CvInvoke.cvCopy(Original, imgMask, imgBinary);
VectorOfVectorOfPoint contoursDetected = new VectorOfVectorOfPoint();
CvInvoke.FindContours(imgBinary, contoursDetected, null, Emgu.CV.CvEnum.RetrType.List, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);
var contoursArray = new List<VectorOfPoint>();
int count = contoursDetected.Size;
for (int i = 0; i < count; i++)
{
using (VectorOfPoint currContour = contoursDetected[i])
{
contoursArray.Add(currContour);
}
}
With this, I get a black image with a tiny bit of white lines. I've racked my brain back and forth and haven't been able to come up with something. Any pointers would be much appreciated!
I think that you need to find which one is the largest area using ContourArea on each one of the contours.
After you find the largest contour you need to fill it (because the contour is just the putline of the blob and not all the pixel in it) using FillPoly and create a mask that as the leaf pixels with value 1 and the everything else with 0.
In the end use the mask to extract the leaf pixels from the original image
I am not so proficient in c# so i attach a code in python with opencv to give you some help.
The resulted image:
Hope this will be helpful enough.
import cv2
import numpy as np
# Read image
Irgb = cv2.imread('leaf.jpg')
R,G,B = cv2.split(Irgb)
# Do some denosiong on the red chnnale (The red channel gave better result than the gray because it is has more contrast
Rfilter = cv2.bilateralFilter(R,25,25,10)
# Threshold image
ret, Ithres = cv2.threshold(Rfilter,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
# Find the largest contour and extract it
im, contours, hierarchy = cv2.findContours(Ithres,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE )
maxContour = 0
for contour in contours:
contourSize = cv2.contourArea(contour)
if contourSize > maxContour:
maxContour = contourSize
maxContourData = contour
# Create a mask from the largest contour
mask = np.zeros_like(Ithres)
cv2.fillPoly(mask,[maxContourData],1)
# Use mask to crop data from original image
finalImage = np.zeros_like(Irgb)
finalImage[:,:,0] = np.multiply(R,mask)
finalImage[:,:,1] = np.multiply(G,mask)
finalImage[:,:,2] = np.multiply(B,mask)
cv2.imshow('final',finalImage)
I recommend you look into Otsu thresholding. It gives you a threshold which you can use to divide the image into two classes (background and foreground). using OpenCV's threshold method you can then create a mask if necessary.
I'm using emgu cv 3.0.0 and I would like to capture frames from a USB cam.
Unfortunately, I get an error while calling Image<Bgr, Byte> image = capture.QueryFrame();
It says, I can't convert from Emgu.CV.Mat to Emgu.CV.Image.
Try this line of code
Image<Bgr, Byte> image = capture.QueryFrame().ToImage<Bgr,Byte>();
In cv v 3.0.0 most methods use Mat for image representation.
You can try this to get the frame from the camera:
Mat frame = new Mat();
_capture.Retrieve(frame, 0);
For conversion to gray:
Mat grayFrame = new Mat();
CvInvoke.CvtColor(frame, grayFrame, ColorConversion.Bgr2Gray);
Also you can see how it works in examples here.
I'm creating an application of watermarking using opencv, I'm not able to set background of image as transparent.
I'm using this code Scalar colorScalar = new Scalar(255,255,255,0);
Can any body help me how to make background transparent. I'm using PNG format image.
targetMat = new Mat(targetSize, scaledImage.type(), colorScalar);
Mat waterSubmat = targetMat.submat((int)offsetY,scaledImage.height(), (int)offsetX, scaledImage.width());
scaledImage.copyTo(waterSubmat);
center = new org.opencv.core.Point(pivotX, pivotY);
Mat rotImage = Imgproc.getRotationMatrix2D(center, degreevaluechange, 1);
Mat resultMat = new Mat(2,3, CvType.CV_32FC1);
colorScalar = new Scalar(255,255,255,0);
Imgproc.warpAffine(targetMat, resultMat, rotImage, targetSize, Imgproc.INTER_AREA, Imgproc.BORDER_CONSTANT, colorScalar);
scaledImage = resultMat.clone();
If you want to load your PNG image with the alpha channel and therefore load your image with transparenty, you have to use this code:
imread("image.png",-1)
You can find more informations in the opencv documentation here:
http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html?highlight=imread#imread
As you see in the documentation provided by Maximus. You need to create a 4 channel Mat:
Mat* targetMat = new Mat(targetSize, CV_8UC4, colorScalar);
vector<int> compression_params;
compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
compression_params.push_back(9);
try {
imwrite("alpha.png", targetMat, compression_params);
}
catch (runtime_error& ex) {
fprintf(stderr, "Exception converting image to PNG format: %s\n", ex.what());
return 1;
}
Then add the parameters and write. (This code is from the documentation)
I am currently using
Capture grabber = new Emgu.CV.Capture(#"M2U00253.wmv");
grabber.QueryFrame();
I want to know that how can I use an image file(.jpg) instead of the video file(.mpg)?
To load a static you can use the following method,
Image<Bgr, Byte> img1 = new Image<Bgr, Byte>("MyImage.jpg");
refer to this link for more information.
I am new to EMGU.CV and I am struggling a bit. Let me start by giving some background of the project, i am trying to track a users fingers, i.e. calculate the users finger tips, but i am struggling a bit. I have created a set of code which filters the depth information to only a certain range and I generate a Bitmap image, tempBitmap, i then convert this image to a greyscale image using EMGU.CV which can be used by cvCanny. Once this is done i apply dilate filter to the canny image to thicken up the outline of the hand to better improve the chance of generating a successful contour, I then try to get the contours of the hand. Now what i have managed to do is to draw a box around the hand, but i am struggling to find a way to convert the contours generated by FindContours to a set of Points i can use to draw the contour with. the variable depthImage2 is a Bitmap image variable i use to draw on before assinging it to the picturebox variable on my C# form based application. any information or guidance you can provide me with will be greatly appreciated, also if my code isnt correct maybe guiding me in a direction where i can calculate the finger tips. I think i am almost there i am just missing something, so any help of any kind will be appreciated.
Image<Bgr, Byte> currentFrame = new Image<Bgr, Byte>(tempBitmap);
Image<Gray, Byte> grayImage = currentFrame.Convert<Gray, Byte>().PyrDown().PyrUp();
Image<Gray, Byte> cannyImage = new Image<Gray, Byte>(grayImage.Size);
CvInvoke.cvCanny(grayImage, cannyImage, 10, 60, 3);
StructuringElementEx kernel = new StructuringElementEx(
3, 3, 1, 1, Emgu.CV.CvEnum.CV_ELEMENT_SHAPE.CV_SHAPE_ELLIPSE);
CvInvoke.cvDilate(cannyImage, cannyImage, kernel, 1);
IntPtr cont = IntPtr.Zero;
Graphics graphicsBitmap = Graphics.FromImage(depthImage2);
using (MemStorage storage = new MemStorage()) //allocate storage for contour approximation
for (Contour<Point> contours =
cannyImage.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE,
Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_EXTERNAL);
contours != null; contours = contours.HNext)
{
IntPtr seq = CvInvoke.cvConvexHull2(contours, storage.Ptr, Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE, 0);
IntPtr defects = CvInvoke.cvConvexityDefects(contours, seq, storage);
Seq<Point> tr = contours.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE);
Seq<Emgu.CV.Structure.MCvConvexityDefect> te = contours.GetConvexityDefacts(
storage, Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE);
graphicsBitmap.DrawRectangle(
new Pen(new SolidBrush(Color.Red)), tr.BoundingRectangle);
}
Contour contours = cannyImage.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_NONE) //to return all points
then:
List<Point[]> convertedContours = new List<Point[]>();
while(cotours!=null)
{
var contourPoints = contours.ToArray(); //put Seq<Point> to Point[], ToList() is also available ?
convertedContours.Add(contourpoints);
contours = contours.HNext;
}
you can draw contour by image Draw functon overload.
just find signature that contains parameter Seq<>
....