I am uploading a picture of a document taken with my smartphone to my Linux server. On my Linux server I am using ImageMagick to cut the edges and do some processing (like gray color coding) to make it look like a scanned document.
Below is one sample image.
I want to trim the image so that only the paper is selected, and do further processing to make it look like a scanned image, similar to what a cam scanner does.
Note: I want the parameters for ImageMagick tool to be generic so that I can use the same command line options to process images taken under different conditions of light.
I agree with #Mark. However, I can offer a starting point that may help you get going in the right direction:
Isolate the Paper:
Assuming the paper is sufficiently contrasted against the background you can use something like:
## make the background transparent
convert 'input_image' \( -clone 0 -fill black -fuzz 10% +opaque "rgb(1,1,1)" -transparent black \) -delete 0 'transp_image'
You will have to change the rgb color values to match the 'white' color of the paper. The display command in imagemagick has a nice utility for this. Also you can play with the -fuzz percentage to isolate the paper only.
Remove the Background: Hopefully the above code will make all areas outside the paper transparent in which case you can trim away the background:
## trim the transparent background away
convert 'transp_image' -trim 'isolat_image'
From there you can do fancier things like changing the perspective. Try looking into -distort in imagemagick (http://www.imagemagick.org/Usage/distorts/#perspective). Though I am not sure how you would apply a distortion in a loop to pictures taken by hand -- each picture would probably require specific input parameters.
Good luck!
Related
I've got a 16x512 image comprised of 16x16 images. I want to seperate them, individually scale each one down to 16x8, then put them all back into their full 16x512. I've got a basic idea, but I'm having trouble executing it.
Using the commands from unix stackexchange, I split by file by using convert -crop 16x16 my_image.png crop-%d.png, which yields 32 images (512 / 16 == 32). My next step was where trouble has started. From askubuntu, I found the command mogrify -resize 16x8 crop-*.png, however this does not yield 16x8 images, but rather 8x8, which I do not want. Furthermore, this post on stackoverflow gives me the command for merging these images, which is convert crop-*.png -append my_image_cropped.png, however it does not yield a 16x512 like I want, but rather 8x256 (the 8 is due to the previous bug, but I still want a height of 512, not 256).
What do I need to accomplish my goals? The image in question can be found on imgur.
Edit: Here are some images which will describe the basic idea
The full image:
Both 16x16 and 16x8 side by side
The finalized image, basically the 16x8 will sit in the 16x16 area (right at the bottom part, that is essential), but won't fully fill it.
I am not sure I understand what you want to do. But if you resize 16x8, Imagemagick will keep aspect ratio. If you want to force it to be exactly 16x8 and can accept distortion, then use the ! flag. But you then say you want to put the 32 pieces back to form 16x512, but the resize will make it 16x256, since you have 32 image of height 8. So you have to resize again. Here is how to do that, if that is really what you want.
Create a gradient image for testing:
convert -size 16x512 gradient: grad.png
Do the processing:
convert grad.png -crop 16x16 -resize 16x8! -append -resize 16x512! newgrad.png
Note that proper Imagemagick syntax reads the input first.
ADDITION:
Given your new information in your comment, try this:
convert grad.png -crop 16x16 -resize 16x8 -gravity northwest -background none -extent 16x16 -append newgrad.png
Change the background color as desired and the gravity setting as desired for positioning.
I was writing a script to change my background on my Linux Machine to a random image from a set of images that contain only solid colors. What I would like to do is expand this script to also theme certain applications (mostly terminal ones) accordingly, at the very least to change the text color, possibly switch from dark to light background, etc. I was wondering what options I have to get the Hex Code for the color in the image. Is there something in bash I can do this with? Would I need to write a program in a more robust language and have the hex-code be the output? Is there a better way of doing this entirely? My searching thus far has been a bit inconclusive.
I would highly recommend to use ImageMagick for this task. The documentation mentions how to extract data from an image.
From "Extracting the average colour":
The average color of an image can be found very quickly by using "-scale" to reduce an image to a single pixel. Here for example is the average color of the built-in "rose:" image. I output the color using the FX Escape Format which
returns a color string that can be used directly IM without change.
user#laptop:~$ convert rose: -scale 1x1\! -format '%[pixel:s]\n' info:-
Will output: srgb(146,89,80)
In your case, replace rose: with an image file of yours, like foo.png.
If you want the output directly in hex notation, use this:
convert rose: -scale 1x1\! -format '%[pixel:s]\n' info:- | awk -F '[(,)]' '{printf("#%x%x%x\n",$2,$3,$4)}'
I'm trying to use optical character recognition (OCR) to read text printed on digital video (DV) tapes. I'm using cropped still frames from the video for the OCR process. The text is white, but there are color artifacts (maybe composite color artifacts) so that the white text has color bleeding onto it (see example below). The colors look to be in magenta-cyan-yellow colorspace, maybe?
OCR results would likely be improved if I could remove/filter those colors to leave only white on the text. Then I can create a binary black/white image. I can do this now, but I suspect results will improve if I can remove colors from the white text before OCR, and this will hopefully help separate the white text from the background image.
Are there any ways, using Imagemagick preferably, to filter out those colors from the white text? I'm not sure of the best way to approach this since there are multiple colors bleeding, and the background changes in each frame. Currently using Imagemagick version 6.9.2-3 Q16 x64 on Windows 7.
Sample full-frame image:
Sample of cropped region with text (note color-bleed and white text blending into background):
I would suggest leveraging ImageMagick's FX & Morphology Dilate to preprocess the image. But to be honest, it'll take a bit of trial & error to find the solution that would work for you. I would also recommend that whatever solution you develop allows graceful error handling (i.e. If attempted OCR process unsuccessful, emit warning, and progress video to next I-frame & repeat.)
Fx Preprocessing
The -fx operator will allow you to create user-defined mathematical expression. Some quick google search about chrome-keys, and other tolerance methods might be helpful. But for many OCR techniques, it's usually common to reduce the colors to a "uniformed" gray scale.
convert aaA7b.png -fx 'intensity' intensity.png
Morphology Preprocessing
Morphology allows common & custom kernels to alter surrounding pixels. As video scanlines + other artifacts are distorting the text, I would recommend exploring Dilate, but there are many other techniques listed in the Usage documents.
Diamond
convert aaA7b.png -fx 'intensity' \
-morphology Dilate Diamond:1 diamond.png
Square
convert aaA7b.png -fx 'intensity' \
-morphology Dilate Square:1 square.png
Plus
convert aaA7b.png -fx 'intensity' \
-morphology Dilate Plus:1 plus.png
Custom
And if you need something more exact, create your own kernel by supplying the following format size: row1 row2 ... rowN. In this example, I'm creating a 3x3 kernel with a single vertical line to offset the video scanlines.
convert aaA7b.png -fx 'intensity' \
-morphology Dilate \
'3x3: nan,1,nan nan,1,nan nan,1,nan' user_defined.png
But YMMV. Also take a look at Fred's TextCleaner script. The -deskew & -sharpen operators will help reduce the noise.
Sample of cropped region with text (note color-bleed and white text blending into background):
I think there's a saying "You can't make steak from a hamburger." or something like that. At some point the background will washout the text in the foreground, and it's time better spent to create a solution that acknowledges this.
I have a PNG which (besides a white spot and transparency in the background) is a pretty straight blue.
I would like to use convert from ImageMagick to partially desaturate it, so that I can create images with the original blue at one extreme, and regular desaturation (I know that color theory allows a lot of desaturations, but I'm just looking for GIMP-style desaturation.)
I would also like to lighten or darken the colors to an image.
Lastly, I would like to change the hue for the bulk of the images, to anything on the hue scale. (The image is a saturated blue.)
I can do all of these in GIMP but I am looking for a way to automate the process. I also want to resize down, but that much was clearer from the docs.
How can I do these adjustments?
This might help. It uses this image as input - I am not so artistic and is a pretty literal interpretation of your teardrop image description...
#!/bin/bash
for hue in $(seq 0 40 160); do
for sat in $(seq 20 40 100); do
convert -label "Sat:$sat,Hue:$hue" input.png -modulate 100,$sat,$hue miff:-
done
done | montage - -frame 5 -tile 3x m.png
I have image.png in truecolor,
palette.png (N colors, where N>256) or text file, where list RGB color palette.
How to get a picture with this palette?
If I use imagemagick:
convert image.png -remap palette.png remap_image.png
It does not work.
convert image.png -map palette.png remap_image.png
Gives a very bad quality. The image is very noisy. File size is bigger than before.
GIMP gives best quality:
Сonvert image to indexed color > use custom palette
But GIMP is GUI. I need to convert a lot images in the console without running the gimp and X.org.
Using a shared palette across multiple images requires a carefully crafted palette. If you don't take great care when using the palette of a single image across many images, the result will be poor.
This needn't be complicated though. If you have accesss to the GIMP (or other tool) which supports truecolor graphics, you can create a large image and fit all of the smaller images into it, then quantize the image to N colors, then use that palette as the source.
you should be able to closely mimic GIMP's behavior in the console using ImageMagick
Once you've got a truecolor image with all the colors you want to quantize,
# Create an 8-bit png from our source, with a 235-color palette as an example.
convert truecolor_source.png -colors 235 palette.png
# Create an 8-bit png from an arbitrary image and use the palette in palette.png
convert sample.png -map palette.png output.png
There are a number of options for down-sampling colors, like dithering. See the ImageMagickv6 example page for an excellent overview with example pictures and code.
Although I still don't exactly understand what you want to do, your currently most recent comment ("Yes, from RGB to palette will set independently. Need set correct quantity of colors"), it sounds like all you want to do is set a strict limit on the amount of colors of a bunch of images, but they don't need to use the same palette.
In that case, the solution is very simple:
convert sample.png -colors 135 output.png
Try playing with the quantization options if the result isn't to your satisfaction.
If the output image is too large for your liking, you can experiment with the -quality option.
If this still isn't satisfactory, please try to explain your goal in a more detailed manner.
Good luck!
cat photo.png | pngnq -s 1 > photoindexed.png
I tend to get good results with the "-remap" (single imge) or "+remap" (multiple images) functions in combination with "-colors". Read up on those functions here. Note that "with "-remap" you provide IM with the final set of colors you want to use for the image, whether you plan to dither those colors, or just replace the ones with their nearest neighbours.", meaning just remapping/replacing might not look good enough, as colors from the input image are simply replaced by those from the palette image. Some form of dithering will be necessary to distribute pixel color conversion errors throughout the output image, because not all colors in the palette match those of the input image.
I'd suggest you use the "-colors N" option for that. This will reduce your output image color count to a maximum of N. By default ImageMagick uses "-dither Riemersma" for this implicitly when you specify "-colors N". The are also other dithering options available.