With a mobile device I take a picture of a flat light object on a dark surface. (for instance a coupon clipped out of a newspaper).
The image is then run through a brightness/contrast filter. If it is too dark, vital components are left out. If it is too bright, the writing on the coupon is lost.
This image is then converted into a bitonal image. Any pixel that is 50% or more dark is converted to black, everything else is white. (done)
I am left with a skewed bitonal image (think of a white trapezoid inside a larger rectangle with a black background).
I need to figure out how to crop the image - which when it's on a black background is easier than when it's on a white background. Then, I have to de-skew the image so it is rectangular instead of trapezoidal, while attempting to preserve aspect.
The end result should be a nicely cropped, bitonal, readable image of the coupon.
To crop your image, you can use the LockBits method and scan through all your pixels to find the first pixel with content from the top, left, right and bottom, respectively. How to use LockBits is described nicely here: https://web.archive.org/web/20141229164101/http://bobpowell.net/lockingbits.aspx
Assuming your image is not rotated, and that the skewing comes from the camera held at an angle against the table where the coupon is being photographed, you should now have a skewed image of the coupon, fitting perfectly within the bounds of the cropped bitmap. You should also know the four corners of the trapezoid.
"Undistorting" an image is not as easy as you might think though. However, good people have solved this problem and you can probably port their code to your own use. Here is a link I used to explore this problem in a similar case some time ago:
http://ryoushin.com/cmerighi/en-US/2007-10-29_61/Image_Distortion_Enhancements
I also have some code stored somewhere if you can't make any sense of what you find.
Related
I have thousands of images of sheet music, in 4:3 aspect ratio, that I want to crop to something closer to 16:9. The images have a lot of whitespace, so at least I want to cut that away.
All the images are different, even the margins aren't always the same.
What kind of algorithm should I use in C# to detect the edges of the staves, so I can determine where to crop the image?
(The green box is where I'd want to crop this image)
I've tried looping through all the pixels, that seems to work, but is extremely inefficient.
Is there a better way?
I have a difficulty as I am trying to render a character with a specific font style to the bitmap image (black and white). My question is the font is basically black and white and I am writing the character in black (against white background), however when I convert it to bitmap image I get a coloured thin outline around the bindery of my character.
Can anyone tell me where that grey color comes from while I am writing it with black color and how can i get ONLY black and white pixels?
The pixels that aren't completely black or completely white are the result of anti-aliasing. Anti-aliasing is used by default since everyone who doesn't know about it probably wants it.
I suggest two alternatives. One, create your bitmap with a one bit per pixel format, which will not give anti-aliasing a chance. Second, you can go through the resulting image after the text has been drawn pixel by pixel and adjust each pixel to either black or white based on a threshold. I.e. if the picture is darker than half then it's black, otherwise it's white. e.g. if (red+green+blue > 383) set_pixel_white() else set_pixel_black(); But you'll need be ready for some rather funny results. You may need to play with the thresholds.
PS there's a better solution, you can tweak anti-aliasing. MSDN You'll set your rendering to System.Drawing.Text.TextRenderingHint.SingleBitPerPixel or something that suits you.
I'm having a problem with masking an image in WinRT. Basically, what I need to do, is to cut out a puzzle shape out of the base image. I have the puzzle shape as a PNG black and white image, where the shape itself is white and the background black and also as a transparent shape of the puzzle piece. This is actually a port of a iOS app, where they used a CGContextClipToMask with the black and white mask to cut out the puzzle piece.
I tried using the Blit from the WriteableBitmapEx to mask the images, but I never achieved the result I wanted, the closest I got was the correctly cut out shape, but with a black background, instead of nothing. What is the correct way of cutting out this shape? Thanks for all the answers!
Indeed, WinRT/XAML in Windows 8 does not have an OpacityMask implementation of other XAML frameworks. You could use WriteableBitmap to manipulate the pixels, but it's a bit slow, especially on ARM devices. A faster solution is to use Direct2D, which has a FillOpacityMask method built right in. Since SharpDX wraps it nicely for .NET you can do that with C# too.
I don't have code, however the simplest case would be to just open PNG file in Photoshop/GIMP/any online transparency tool and just map black pixels alpha to zero.
Another example would be doing that in code directly,
WriteableBitmapEx has function to change each pixel,
all you have to do, is loop through all black pixels and change alpha to 0.
I have an image frame:
1 http://i48.tinypic.com/wugmc2.png
The image resolution is: 533x300
Using GDI+ I Re-size the image to 300x533:
Now as you can see it distorted the width/height of the border and shrunken Santa Claus...
Is there a way using GDI+ c# to prevent this distortion of the image frame?
Scaling the image will always result into a skewed santa. If that is not what you are looking for, try creating separate images of your santa and the border.
If the border will stay that simple as a red line, I am almost sure that there is a simple control for just drawing red borders in GDI. If you are going to create some christmas border with branches and trees, you need a bit more smaller images to separate this problem.
Create a separate santa to use as an overlay
Create separate images for the corners
Create separate tillable images for vertical and horizontal borders
Then place the images by yourself and tile the images in the centers like so:
I have never worked with GDI, but this is a general solution for scaling borders.
I found an article on image processing from here: http://www.switchonthecode.com/tutorials/csharp-tutorial-image-editing-saving-cropping-and-resizing Everything works fine.
I want to keep the high quality when resizing the image. I think if I can increase the DPI value I can achieve this. Does anyone know if this is possible? And if so, how can I implement it in C#?
For starters, it's worth pointing out that there are two general categories of images; vector [e.g. SVG, WMF, Adobe Illustrator and Corel Draw Graphics] and bitmap (also called raster) images [e.g. Bitmap, JPEG and PNG Images].
Vector images are formed from a series of mathematical equations and/or calculations. Bitmap images, on the other hand, are made up of individual dots (pixels) each corresponding to a particular feature on the object the image is taken of.
If it should happen that you want to resize an image, the first thing to consider is if it is a bitmap or vector image. By virtue of the fact that vector images are obtained from calculations, they can be perfectly resized without losing any detail. The case is different for bitmap images. Since each pixel is independent of the other, when you desire to resize it, you are simply increasing or decreasing the source to target pixel ratio.
So in order to double the size of a vector image, simply multiply the target dimensions by two and everything comes out all right. If you should apply the same effect on a bitmap, you are actually increasing each source pixel to cover four pixels (two rows of two horizontal pixels).
Of course, by applying interpolation and filtering, the computer can "smooth" out the edges of the target pixels so they seem to blend into each other and give the appearance of a reasonably resized image but this output is never the same as resizing a vector image; vector images resize perfectly.
You also mentioned DPI in your question. DPI is essentially the number of pixels that correspond to an inch when the image is printed not when it is viewed on a screen. Therefore by increasing the DPI of the image, you do not increase the size of the image on the screen. You only increase the quality of print [which needless to say depends on the maximum resolution of the printer].
If you really desire to resize the image and the image is a bitmap, as a rule of thumb, do not increase the size beyond 200% of the original image's size else you'll lose the quality.
You can see this answer for code to resize bitmap images.
To see a sample vector image, go to this link.
Note Try zooming in and out of the image to see how well it resizes.
A typical bitmap are the StackOverflow sprites. They do not keep their quality resized.
Further Reading
Vector Graphics: http://en.wikipedia.org/wiki/Vector_image
Bitmap Graphics: http://en.wikipedia.org/wiki/Bitmap_image
Simply If the original image is smaller then the re-sized image then there is hardly anything you can do. Rest is a research problem.
This would only be possible if it's a vector graphic. Look into SVG. Otherwise, I think you might need Silverlight or Flex for that part.
What you're asking isn't really possible. You can't enlarge an image while maintaining the same quality.
If you think about an image as a mapped array of pixels (literally, a "bit-map"), this makes sense. The image is saved with a fixed amount of data, and that's all you have to work with when you resize it. Any examples to the contrary (like TV shows, as suggested by one of the comments) are purely fictional.
The best that you can do is set the InterpolationMode property of the Graphics object you're using to do the resizing to "HighQualityBicubic", which is the highest quality smoothing algorithm supported by GDI+ and in fact by every major graphics package on the market. It's the best that even Adobe Photoshop has to offer. Essentially, interpolation means that the computer is calculating the approximate value of the new pixels you're adding to make the image larger from the relative values of neighboring pixels. It's a "best guess" method, but it's the best compromise we've come up with yet.
At the very least, the resulting images won't have "jaggies" or rough, pixelated lines.
Sample code:
Graphics g;
g.InterpolationMode = Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
// ... insert the rest of your code here
Beyond that, it's worth noting that GDI+ (which the .NET Framework uses internally for graphics routines) works best with image sizes that are multiples of 16. So if it all possible, you should try and make the width and height of your resized images a multiple of 16. This will preserve as much of the original image quality as possible.
The ideal solution is to switch to vector graphics that can be resized at will. Instead of pixel information, they contain mathematical information used to draw or "render" the image. Read more on Wikipedia.
let's try metadata in GDI+, may be it can suit your request