I'm building a c# app to take photos of visitors for ID badges. I have found a c# wrapper for web cams so can take a snap shot easily, however I need to set the images to a certain number of pixels ideally with the persons head filling most of the area.
I imagine the best way to do this is to allow the end user to drag out a rectangle over the initial image with fixed x and y ratio covering the persons face. This would crop the image and do any resolution adjustment necessary.
Does anyone know of an example similar to this? I think I know how to do the rectangle and get my co-ordinates for the image cropping apart from fixing an x and y ratio. Obviously an example would be quicker than trying to write my own.
As of .Net 3.0, System.Windows.Media.Imaging provides a CroppedBitmap class that inherits from BitmapSource. Its constructor takes a BitmapSource and an Int32Rect. If you pass it your original image and your rect, it will return a cropped image as a BitmapSource.
Related
Similar to my previous question which I as yet have not solved (Comparing Frames of a live Feed) I have another issue.
Scenario
I have an image taken by a camera that contains a rectangle in it. I need to crop the image to only show the rectangle plus a small margin.
My Efforts
I have accomplished this by iterating through the pixels using LockBits and attempting to find potential edges but these seems terribly slow and inefficient
My Thoughts
I was thinking I could take an empty image as a baseline and then remove the differences between the two, however I cannot be sure that the lighting will be exactly the same and that potential contaminants such as an accidental fly getting into the image will not be present which could muck up this process.
Is there any easier way? The rectangle should (usually) be in the bottom left corner, but not always (long story) but this cant be relied upon.
My Environment
Visual Studio 2012 (2010 if neccessary is available)
Ueye camera
C#
The images are of type System.Drawing.Bitmap
The rectangle will often be something like a credit card or an ID card or anything of a similar size and shape
The empty image (background) looks like this:
Using EmguCV you can detect shapes such as a rectangle. Click here for the emgu code. Once you have detected the rectangle it is fairly easy to crop it out using a new Bitmap with the size of the rectangle.
The sample demonstrates how to crop the image from specific Picturebox control into destination Picturebox control using mouse selection or specified coordinates.
1.How to use mouse to select an area (rectangle) in a Picturebox control.
2.How to crop the image by the rectangle.
http://code.msdn.microsoft.com/windowsdesktop/CSWinFormCropImage-d4beb1fa
I've got a large image in memory which I convert to an System.Windows.Media.ImageBrush and use it as the Fill for a System.Windows.Shapes.Rectangle. You can move this rectangle around with your cursor.
Basically I want to use the rectangle as a "viewport". Thus I need to change which parts of the image get displayed within the rectangle, i.e., define a rectangular subsection of the image.
How can I do that?
I see ImageBrush.Viewport but that doesn't seem to mean the same thing.
I'm open to alternative solutions that don't involve a rectangle, such as drawing directly on a canvas or something, but AFAIK WPF doesn't let you access pixel data directly (at least not easily).
To achieve this your going to have to create your own rectangle user control to allow the user to create/resize a rectangle. Then I would create a CroppedBitmap of the image in the rectangle portion Cropped Bitmap MSDN Stackoverflow example
Edit
No, no, no #Mark, You dont turn the CroppedBitmap into a UserControl. You create a USerControl that exposed the CroppedBitmap. Basically, you create a UserControl with the following DependencyProperties
The Image
The Width of he cropped portion
The Height of the cropped portion
The Left of the cropped portion
Top of the cropped portion
Then as soon as any of these properties your DP callback will do a RenderTargetBitmap Crop of the new region.
Background
I want to be able to get the drawn dimensions of a zoomed image inside the picturebox (I'll explain below).
The PictureBox.ImageRectangle property seems to be exactly what I'm looking for because it shows the height and width of the resized image, as well as it's relative top, left position inside the control.
The trouble is PictureBox.ImageRectangle is private and so I can't read the values without using reflection (which is obviously not ideal).
Actual Question
My question is, is there another way that I can easily get to these values without writing a method to calculate what the values "ought" to be? I can do that easily enough, but I feel I'd be reinventing the wheel.
Context:
I'm writing a simple image processing app in C# and one of the things it has to do is allow the user to draw a selection around a portion of the image (a lot like the Marquee tool in Photoshop).
I need to know the dimensions of the rendered image so I know where to set the bounds of my marquee tool and also to translate the values of the drawn rectangle to points on the scaled bitmap inside the control.
My answer look simple so maybe I'm missing something, but I think Control.DisplayRectangle suits your need.
EDIT
OK, missed the point; however see How to get the value of non- public members of picturebox?
if you want to access dimension of the image in picture box you can use
GraphicsUnit units = GraphicsUnit.Point;
RectangleF imgRectangleF = pictureBox1.Image.GetBounds(ref units);
Rectangle imgRectangle = Rectangle.Round(imgRectangleF);
I'm diving into something without sufficient background, but I feel like there may be simple solutions that don't require me to have in depth knowledge of the topic.
What I am trying to do is have an image co-ordinate system. Basically the user will supply an image, like a house plan. They can then click on points in the image and create markers (like google maps). The next time they retrieve the map, all the markers they added before are there and they can add new ones.
I need to identify the points these markers are located on so I can store that information. I also need to be able to create a layer on the image that contains the markers and renders them in the exact locations they were placed.
I imagine the easiest way to do this is to use pixel co-ordinates...the rub here is that the image won't be a fixed size since there is a web application and an IPad application, so the co-ordinate system needs to work as long as the image is in the same size ratio.
The server size is .NET and as mentioned there is an IPad app, so the solution needs to be viable given that tech stack.
Any ideas?
Instead of using pixel coordinates in absolute terms, you can use the 0 to 1 range. The top left corner is (0,0), bottom right is (1,1) and the center of the image is (0.5,0.5). This way not matter what image size (or zoom level) you have, the markers will always be in the same place.
My suggestion is don't try to figure out the correlation between the actual image and the coordinates. The only thing I would do is use the resolution of the image, aka 800x600 and use that for your grid. Then overlay your markers using that grid on the image. The points you'd remember would just be X and Y values and maybe a tag name/id.
The ImageList has a method named "Draw":
imageList.Draw(graphics, bounds.X, bounds.Y, bounds.Width, bounds.Height, imgIndex);
I use this method to draw an image on a graphics object of a PrintDocument. When using the original image size (16 x 16 pixels), the image is drawn correct. If however, I change the bounds size, nothing is drawn. Even changing the size to 32 x 32 (double size) has no effect. Nothing is drawn. I need to change the drawn size because of the different dpi ... Where am I gong wrong ?
Edit: The solution seems to be simply to use the g.DrawImage method instead. Why imageList.Draw() doesn't draw is still a mistery to me ...
g.DrawImage(imageList.Images[imgIndex], bounds);
ImageList.Draw() is a bit unusual, it takes advantage of the built-in support that the native image list code inside of Windows has for rendering an image in the list. This is an optimization, it avoids the cost of converting the internal image as stored in the native image list back to a managed Image object.
One side-effect however is that this drawing happens without regard for any of the transforms that were applied to the Graphics object. A 16x16 image in the list is going to be rendered as 16x16 pixels on paper. Which is indeed a bit hard to find back, printers have very high resolution (600 dots per inch is typical), that image turns into a decimal point.
Image lists were really meant to be the source of images for the TreeView and ListView controls, it is not a good general purpose collection object for images. Like a List<Image>. Your workaround is good, the Image property converts the internal bitmap back to a managed Image, Graphics.DrawImage() will then scale it appropriately to get a size on paper that's close to the size on the screen. However with the graininess you get from making an image 6 times larger. Note that you should Dispose() that object.