Convert colored scanned image to black-white image - image-processing

I have scanned images like this where the background color is not necessarily consistent. When I use an ImageMagick command like this, it will apply a fixed threshold, which is not good for images without a consistent background.
convert in.jpg -threshold 35% -type bilevel -monochrome -compress LZW out.pdf
Can anybody provide a robust way to generate the corresponding monochrome image maintaining all the texts?
I think the best method probably should be based on deep learning. But DL may take too many resources to run. Non-DL methods are also welcome if it can render reasonably good results.

You can improve that using -lat function in Imagemagick as follows:
Input:
convert coahuila.jpg -colorspace gray -negate -lat 50x50+10% -negate result.jpg
Note: I suggest saving as PNG or TIFF to avoid extra JPG compression. I only saved as JPG since this forum has size restrictions.

You obtain a good result with adaptive thresholding (for instance size 43, offset 28 but this setting is not critical).

Here is another Imagemagick 6 approach using division normalization and thresholding. Then some morphology to connect the rows of text. Then followed by connected components processing to find the largest black connected region. From that we extract the bounding box and use its dimension to crop the normalized image and thresholded image and pad back out with white to the size of the original image.
Input:
dims=$(convert coahuila.jpg -format "%wx%h" info:)
bbox=$(convert coahuila.jpg \
-colorspace gray \
\( +clone -blur 0x20 \) \
+swap \
-compose divide -composite \
-threshold 70% \
-type bilevel \
+write coahuila_div.png \
-morphology open rectangle:1x55 \
-morphology close rectangle:3x1 \
-define connected-components:verbose=true \
-define connected-components:mean-color=true \
-define connected-components:keep-top=1 \
-connected-components 8 coahuila_ccl.png | \
grep "gray(0)" | awk '{print $2}')
convert coahuila_lat.png \
-crop $bbox +repage \
-background white -gravity center -extent $dims \
coahuila_processed.png
Division Normalized and Thresholded Image:
Morphology Connected Image:
Final Result:
Note if using Imagemagick 7, change convert to magick and also you can replace -threshold 70% to -auto-threshold otsu.
ADDITION
This version pads the bounding box to avoid cropping too close to the text.
dims=$(convert coahuila.jpg -format "%wx%h" info:)
bbox=$(convert coahuila.jpg \
-colorspace gray \
\( +clone -blur 0x20 \) \
+swap \
-compose divide -composite \
-threshold 70% \
-type bilevel \
+write coahuila_div.png \
-morphology open rectangle:1x55 \
-morphology close rectangle:3x1 \
-define connected-components:verbose=true \
-define connected-components:mean-color=true \
-define connected-components:keep-top=1 \
-connected-components 8 coahuila_ccl.png | \
grep "gray(0)" | awk '{print $2}' | tr "x" "+" )
pad=10
ww=$(echo $bbox | cut -d+ -f1)
hh=$(echo $bbox | cut -d+ -f2)
xo=$(echo $bbox | cut -d+ -f3)
yo=$(echo $bbox | cut -d+ -f4)
ww=$((2*pad+ww))
hh=$((2*pad+hh))
xo=$((xo-pad))
yo=$((yo-pad))
convert coahuila_div.png \
-crop ${ww}x${hh}+${xo}+${yo} +repage \
-background white -gravity center -extent $dims \
coahuila_processed.png
Result:
Adjust the pad as desired.
I make no claim that this is a universal solution. Some adjustment will be needed if the text is larger or the spacing is larger between lines, etc.

Related

Make transparent regions using a mask

I have a batch of images that need a transparent background. I am able to create a black/white mask of the lighter and darker regions and want to use this mask to keep the pixels, which are white in the mask unchanged and set all pixel to transparent, which are black. The best outcome so far I got with
convert $FILE -rotate "-90<" $ROTATED
convert $ROTATED \
+dither \
-colors 2 \
-fill black \
-draw 'color 0,0 floodfill' \
-flop \
-draw 'color 0,0 floodfill' \
-flop \
-white-threshold 0 \
$MASK
convert $ROTATED -mask $MASK -compose copy-opacity -composite $OUT
But the last command just "ghosts" the whole image. How can I "cut out" the black pixels and keep the white pixels unchanged?
This is what I get so far.
You simply need to remove the "-mask" from your command line leaving your mask image (and add -alpha off). So the following works fine for me in ImageMagick 6.
Input:
convert star.png \
+dither \
-colors 2 \
-fill black \
-draw 'color 0,0 floodfill' \
-flop \
-draw 'color 0,0 floodfill' \
-flop \
-white-threshold 0 \
mask.png
convert star.png mask.png -alpha off -compose copy-opacity -composite out.png
Mask:
Result:
Download the result to see that the background is fully transparent.
If using Imagemagick 7, then change convert to magick
ADDITION
Here is one way to do that with MPR. Note the +swap.
convert star.png \
-write mpr:star \
+dither \
-colors 2 \
-fill black \
-draw 'color 0,0 floodfill' \
-flop \
-draw 'color 0,0 floodfill' \
-flop \
-white-threshold 0 \
mpr:star \
+swap \
-alpha off \
-compose copy-opacity -composite \
out.png
You can also do it with a clone and parentheses.
convert star.png \
\( +clone \
+dither \
-colors 2 \
-fill black \
-draw 'color 0,0 floodfill' \
-flop \
-draw 'color 0,0 floodfill' \
-flop \
-white-threshold 0 \) \
-alpha off \
-compose copy-opacity -composite \
out.png
I get the same result as above.

How to append a same image to multiple images using imagemagick

Hello I want to add a same image to the left side of multiple images. First image is a legend and it common for all the 6 images which I later want to montage 3x2.
I tried this command below before montaging and it did not work. I wanted to see if I could make it work without adding a for loop, which slows down the code.
convert +append image_3_1.png image_1_[1-6].png -geometry +10+0 test.png
I want the image_3_1 added to all the 6 images starting with image_1. Any ideas?
Your question is unclear about:
what your input and expected output images look like or how big they are,
whether you actually need the intermediate images or just the montage,
what the actual issue is with for loops
So here are some ideas...
Option 1
This one avoids for loops and multiple invocations of magick by using a single magick and loading the side image just once and cloning it in memory:
magick side.png \
\( +clone image_1.png +append -write out_1.png +delete \) \
\( +clone image_2.png +append -write out_2.png +delete \) \
\( +clone image_3.png +append -write out_3.png +delete \) \
\( +clone image_4.png +append -write out_4.png +delete \) \
\( +clone image_5.png +append -write out_5.png +delete \) \
image_6.png +append out_6.png
It produces 6 output files as follows:
Option 2
This one avoids for loops by running 6 copies of magick in parallel:
magick side.png image_1.png +append out_1.png &
magick side.png image_2.png +append out_2.png &
magick side.png image_3.png +append out_3.png &
magick side.png image_4.png +append out_4.png &
magick side.png image_5.png +append out_5.png &
magick side.png image_6.png +append out_6.png &
wait
It produces the same 6 output files as above.
Option 3
This does the same by using GNU Parallel to do it more succinctly:
parallel magick side.png image_{}.png +append out_{}.png ::: {1..6}
Option 4
If you don't need the intermediate files, and just want the montage:
parallel -k magick side.png {} +append ppm:- ::: image_*png | magick montage -tile 2x3 -geometry +5+5 ppm:- montage.png
Option 5
This is much the same, avoiding producing the intermediate output files, and also avoiding using GNU Parallel:
magick side.png \
\( +clone image_1.png +append -write ppm:- +delete \) \
\( +clone image_2.png +append -write ppm:- +delete \) \
\( +clone image_3.png +append -write ppm:- +delete \) \
\( +clone image_4.png +append -write ppm:- +delete \) \
\( +clone image_5.png +append -write ppm:- +delete \) \
image_6.png +append ppm:- | magick montage -background black -geometry +5+10 -tile 2x3 ppm:- montage.png
Option 6
This one uses no for loops, a single process, no separate montage command and generates no intermediate files:
magick side.png -write MPR:side +delete \
\( MPR:side image_1.png MPR:side image_2.png +append \) \
\( MPR:side image_3.png MPR:side image_4.png +append \) \
\( MPR:side image_5.png MPR:side image_6.png +append \) \
-append montage.png
Replace the +append and -append with -smush for more layout and inter-image spacing flexibility.
Option 7
Maybe something like this with -smush:
magick side.png -write MPR:side +delete -background cyan \
\( MPR:side image_1.png MPR:side image_2.png +smush 10 \) \
\( MPR:side image_3.png MPR:side image_4.png +smush 10 \) \
\( MPR:side image_5.png MPR:side image_6.png +smush 10 \) \
-smush 30 montage.png
My guess is that option 6 would be the fastest on most machines in most circumstances, if it is flexible enough for you. If you need more flexibility, go with option 7 or 5.
Keywords: ImageMagick, image processing, montage, layout, parallel, smush.

How to create watermark like shutterstock with imagemagick

I want to create image watermark like Shutterstock. I have tried but not able to replicate it. I tried with the following command. The issue is for me is i not able to add diagonal random text to image as Shutterstock does. I have tried many options with no luck.
infile="zoom.jpg"
ww=$(convert -ping "$infile" -format "%[fx:w-1]" info:)
hh=$(convert -ping "$infile" -format "%[fx:h-1]" info:)
convert "$infile" \
-fill "graya(100%,0.75)" \
-draw "line 0,0 $ww,$hh line $ww,0 0,$hh" -alpha off \
-fill "graya(50%,0.25)" \
tile_aqua_500_text_x_text.jpg
composite -dissolve 35 -gravity center logo.png tile_aqua_500_text_x_text.jpg tile_aqua_500_text_x_text.jpg
convert -background none -size 220x320 xc:none -font DejaVu-Sans-Bold -pointsize 30 \
-gravity North -draw "rotate -22 fill grey text 20,10 'knot9'" \
-gravity West -draw "rotate -27 fill grey text 5,15 '89898989'" \
miff:- |\
composite -dissolve 70 -tile - tile_aqua_500_text_x_text.jpg tile_aqua_500_text_x_text.jpg
width=`identify -format %w tile_aqua_500_text_x_text.jpg`; \
convert -background '#0008' -fill white -gravity center -size ${width}x30 -pointsize 10 -font DejaVu-Sans-Bold\
caption:"\nThis image is Copyrighted by Knot9 \n www.knot9.com | Image Id: 89898989\n" \
tile_aqua_500_text_x_text.jpg +swap -gravity south -composite tile_aqua_500_text_x_text.jpg
My Output is
Requirement is
In ImageMagick, you can do the following. Create a small text image on a transparent background using label:. Rotate it. Pad it to control the spacing. Tile it out to fill the image. Then composite the tiled out image over your background image.
Image:
convert lena.png \
\( -size 100x -background none -fill white -gravity center \
label:"watermark" -trim -rotate -30 \
-bordercolor none -border 10 \
-write mpr:wm +delete \
+clone -fill mpr:wm -draw 'color 0,0 reset' \) \
-compose over -composite \
lena_watermark.png
If using ImageMagick 7, then change convert to magick
See https://imagemagick.org/Usage/canvas/#tile_memory for tiling

Misalignment of a position after resizing an image with ImageMagick

I want to resize several images and overlay them on a background image by using Imagemagick.
I wrote following code.
convert -size 500x1000 xc:white \
-page +100+200 \( aaa.jpg -resize 50x \) \
-page +200+300 \( bbb.jpg -resize 50x \) \
..............
-layers flatten flatten_img.jpg"
I wanted to put the "aaa.jpg" on (100,200),
and the "bbb.jpg" on (200,300),
but the position of them were misaligned.
For example, the "aaa.jpg" was positioned on (33,66).
If I didn't resize them before doing "-page",
that is,
convert -size 500x1000 xc:white \
-page +100+200 aaa.jpg \
-page +200+300 bbb.jpg \
......
-layers flatten flatten_img.jpg"
the position of them were right.
How Can I put them in the right places ?
Thank you in advance.
I can solve the problem.
convert -size 500x1000 xc:white \
\( aaa.jpg -resize 50x50 -repage +50+100 \) \
\( bbb.jpg -resize 100x100 -repage +100+200 \) \
-layers flatten final.jpg

Generate a stack of Polaroid-like photos from existing images using ImageMagick

I would like to be able to take 5 JPG images and process them with ImageMagick to create an effect showing the photos as a stack of Polaroid-like prints.
Assuming all photos are the same aspect ratio, they need to be resized to the same size, a 10px Polaroid-like border applied, then all slightly rotated and offset such that images below the top one are partially visible around the edges.
The rotation/offset doesn't need to be random as such - it could be hand-coded for each image in the stack if it is easier than doing it truly random?
Here is an example of the effect I am aiming for:
Can someone help with the correct parameters to use - I'm assuming we would want to use convert?
Edit: I already knew about the example contained on the ImageMagick page, but it doesn't specifically address my requirements - they clone the original image, they don't use multiple separate images. They also don't do a great job of explaining in each example exactly what every option does - they assume you already have spent hours (or days!) experimenting with the millions of options available. A bit difficult for someone who has never used the tool to master without a lot of work.
convert thumbnail.gif \
-bordercolor white -border 6 \
-bordercolor grey60 -border 1 \
-bordercolor none -background none \
\( -clone 0 -rotate `convert null: -format '%[fx:rand()*30-15]' info:` \) \
\( -clone 0 -rotate `convert null: -format '%[fx:rand()*30-15]' info:` \) \
\( -clone 0 -rotate `convert null: -format '%[fx:rand()*30-15]' info:` \) \
\( -clone 0 -rotate `convert null: -format '%[fx:rand()*30-15]' info:` \) \
-delete 0 -border 100x80 -gravity center \
-crop 200x160+0+0 +repage -flatten -trim +repage \
-background black \( +clone -shadow 60x4+4+4 \) +swap \
-background none -flatten \
poloroid_stack.png
... it would be great if someone could expand on this example and show me how to modify it to achieve my desired results as above.
Here is the command I found to give a pretty good result for what I needed - thanks to #Jim Lindstrom for putting me on the right track.
convert \
img-5.jpg -thumbnail 300x200 -bordercolor white -border 10 \
-bordercolor grey60 -border 1 -bordercolor none \
-background none -rotate -4 \
\
\( img-2.jpg -thumbnail 300x200 -bordercolor white -border 10 \
-bordercolor grey60 -border 1 -bordercolor none \
-background none -rotate 6 \
\) \
\
\( img-3.jpg -thumbnail 300x200 -bordercolor white -border 10 \
-bordercolor grey60 -border 1 -bordercolor none \
-background none -rotate -2 \
\) \
\
\( img-1.jpg -thumbnail 300x200 -bordercolor white -border 10 \
-bordercolor grey60 -border 1 -bordercolor none \
-background none -rotate -4 \
\) \
\
\( img-4.jpg -thumbnail 300x200 -bordercolor white -border 10 \
-bordercolor grey60 -border 1 -bordercolor none \
-background none -rotate 4 \
\) \
\
-border 100x80 -gravity center +repage -flatten -trim +repage \
-background black \( +clone -shadow 60x4+4+4 \) +swap -background none \
-flatten stack.png
Here is the output I get from my images using the above command:
It's not perfect yet, I have some more tweaks I'd like to do which I'll ask about in a separate question.
The docs for "convert" show almost exactly how. Search for "nice looking pile of photos" on http://www.imagemagick.org/Usage/thumbnails/#polaroid
Here's another way of doing it that makes, hopefully, clearer how one would sub in their own photos:
# create four images we want to use as our polaroid stack (I'm using the same one for all
# one, but you don't have to)
curl -O http://www.imagemagick.org/Usage/thumbnails/thumbnail.gif
cp thumbnail.gif thumbnail1.gif
cp thumbnail.gif thumbnail2.gif
cp thumbnail.gif thumbnail3.gif
cp thumbnail.gif thumbnail4.gif
rm thumbnail.gif
# You can easily see the recurring portion of this command. You could build
# it up programmatically and then execute it, for however many images you want.
# I've also simplified the example in their docs by hard-coding some rotation
# angles. Feel free to get fancy, or just hard code an array of them and keep
# grabbing the next one.
convert \
thumbnail1.gif \
-bordercolor white -border 6 \
-bordercolor grey60 -border 1 \
-bordercolor none -background none \
-rotate 20 \
-trim +repage \
\
\( \
thumbnail2.gif \
-bordercolor white -border 6 \
-bordercolor grey60 -border 1 \
-bordercolor none -background none \
-rotate -8 \
-trim +repage \
\) \
-gravity center \
-composite \
\
\( \
thumbnail3.gif \
-bordercolor white -border 6 \
-bordercolor grey60 -border 1 \
-bordercolor none -background none \
-rotate 3 \
-trim +repage \
\) \
-gravity center \
-composite \
\
\( \
thumbnail4.gif \
-bordercolor white -border 6 \
-bordercolor grey60 -border 1 \
-bordercolor none -background none \
-rotate -17 \
-trim +repage \
\) \
-gravity center \
-composite \
\
-crop 200x160+0+0 +repage -flatten -trim +repage \
-background black \( +clone -shadow 60x4+4+4 \) +swap \
-background none -flatten \
\
poloroid_stack.png
I use Simpon Hampel Code with some change in this :
How Margin Image with shadow in imagemagick?
please check it..

Resources