im getting the most existing colors of an image and display it with the "histogram" funktion like
convert image.jpg -scale 100x100 -gravity \
center -crop 50% -dither None -remap color_map.gif \
-format %c histogram:info:
22: ( 0, 0, 0) #000000 black
881: (119,133,142) #77858E rgb(119,133,142)
268: (186, 84, 29) #BA541D rgb(186,84,29)
662: (212,212,212) #D4D4D4 grey83
20: (244,203, 98) #F4CB62 rgb(244,203,98)
647: (255,255,255) #FFFFFF white
Ho can i work now with this output? i want to save the most existing color in my database, but i dont know how to get now only the color with the number 881.
Can any one help me?
If you want to do this purely from the shell (assuming Bash-like Unix environment), something like this would work:
convert image.jpg -scale 100x100 -gravity center \
-crop 50% -dither None -remap color_map.gif \
-format %c histogram:info: | sort | tail -n1 | \
sed -e 's/.*\(#[0-9A-F]\+\).*/\1/'
That takes the output from ImageMagick, sorts it so the largest color count is on the bottom, takes just that line, then extracts the color hex from the line. You can tweak the sed regex if your goal is to get the decimal rgb values instead of the hex.
So for your example image, the output should be just:
#77858E
Related
I would like to create a hotfolder for my motion camera, into which I can drop images marking areas, which should be excluded in motion recognition via a *pgm mask. On these images, there is a small area marked with a transparent box with a magenta colored outline. My aim is to replace this box and outline with a black solid box and the rest of the image with white. (Tried to post samples here, but not enough reputation to do so.)
I know how to do this "by foot" using gimp, but I cannot figure out a clever and simple way achieving this with imagemagick.
I tried googling for solutions with -trim and -virtual-pixel, but no luck. Any help would be appreciated.
I'll do this step-by-step so you can see the intermediate parts in case you are on Windows and bash doesn't work.
First, let's make make everything that is not within 10% of your magenta colour, namely rgb(225,75,130), into lime green:
magick source.jpg -fill lime -fuzz 10% +opaque "rgb(225,75,130)" result.png
Ok, now let's get the trim box - i.e. all the constant junk that ImageMagick could trim off to focus on the magenta bit.
magick source.jpg -fill black -fuzz 10% +opaque "rgb(225,75,130)" -format '%#' info:
14x66+426+118
So your magenta box is 14x66pixels and located at offset 426,118 from the top-left. Now we want to get those in bash variables w,h,x,y. We need to change x and + into spaces using tr:
read w h x y < <(magick source.jpg -fill black -fuzz 10% +opaque "rgb(225,75,130)" -format '%#' info: | tr 'x+' ' ')
If we print this we get:
echo $w, $h, $x, $y
14, 66, 426, 118
Now we want to draw a rectangle, but that needs top-left and bottom-right, so we need to do some maths:
((x1=x+w))
((y1=y+h))
Ok, now we can load the original image, make it fully white, then draw our black rectangle:
magick source.jpg -threshold -1 -fill black -draw "rectangle $x,$y $x1,$y1" -depth 8 mask.pgm
So, the whole thing boils down to:
#!/bin/bash
read w h x y < <(magick source.jpg -fill black -fuzz 10% +opaque "rgb(225,75,130)" -format '%#' info: | tr 'x+' ' ')
echo $w, $h, $x, $y
((x1=x+w))
((y1=y+h))
magick source.jpg -threshold -1 -fill black -draw "rectangle $x,$y $x1,$y1" -depth 8 mask.pgm
There are other (maybe more elegant) ways of doing it, using flood-fills and/or connected components but I didn't want it to rely on your magenta box being "watertight", i.e. not rely on the sides being continuous and complete.
Also, if the size of your images is known and constant, you can avoid reloading the original and making it white by thresholding like I do in the last line and just create a canvas of the known dimensions, i.e.:
magick -size ${W}x${H} xc:white -fill black -draw "rectangle $x,$y $x1,$y1" -depth 8 mask.pgm
How do I adjust the color ratio of a gradient?
I currently use the following to create my gradient.
convert -size 200x600 gradient:none-black output.png
Although at least one acceptable solution has been provided, here are a couple other ideas...
Example 1: This command creates a red-blue gradient of the finished dimensions, crops it into a top and bottom half, resizes them to 40 and 60 percent of the input height, and appends them back to make a single image. What started as the color at the exact vertical center is now at 40% down from the top with clean gradients going up and down from there.
convert -size 200x600 gradient:red-blue -crop 1x2# \
\( -clone 0 -resize 100x40% \) \( -clone 1 -resize 100x60% \) \
-delete 0,1 -append result.png
That splits the gradient image into a top and bottom half, then inside parentheses it resizes each to the required proportion. After that it deletes the 50/50 crops from before the parentheses, appends the two resized remaining images, and writes the output.
Example 2: This next example starts by creating the red-blue gradient in the final dimensions, then sets variables to hold the top color, the exact middle color, and the bottom color.
Then inside the first parentheses it clones and crops the image to 60% its original height. It uses "-sparse-color" to fill that with a gradient from "color1" to "color2".
Inside the second parentheses it clones and crops the image to 40% its original height, and using "-sparse-color" again it fills it with a gradient from "color2" to "color3".
After creating those two gradients, delete the original, append the other two together, and write the output.
convert -size 200x600 gradient:red-blue \
-set option:color1 "%[pixel:p{0,0}]" \
-set option:color2 "%[pixel:p{0,h/2}]" \
-set option:color3 "%[pixel:p{0,h}]" \
\( -clone 0 -extent 100x60% \
-sparse-color barycentric "0,0 %[color1] 0,%[h] %[color2]" \) \
\( -clone 0 -extent 100x40% \
-sparse-color barycentric "0,0 %[color2] 0,%[h] %[color3]" \) \
-delete 0 -append result.png
Maybe you want this, where you get to the half-red/half-blue colour just 20% of the way down the height of the image. It is done by creating two gradients of different lengths and putting them back-to-back:
midcolour="rgb(127,0,127)"
convert -size 100x20 gradient:red-"$midcolour" \
-size 100x80 gradient:"$midcolour"-blue \
-append result.png
Another way is to put 3 single pixels together in a row and then resize that up to what you want. I know you want the middle to be 40% red and 60% blue, but, for ease of viewing, I'll make it lime green:
convert -size 1x1 xc:red xc:lime xc:blue -append -resize 100x100\! result.png
You would change lime to something like "rgb(100,0,155)".
I am not quite sure I understand. But if you want to start with 90% transparent (10% opaque black) and end with black. You can do:
convert -size 200x600 gradient:"graya(0,0.1)-black" output.png
graya means gray with alpha. So graya(0,0.1) is gray(0) or black with 0.1 fraction opacity, so 90% transparent.
Perhaps this is what you want:
Normal 50-50:
convert -size 200x600 gradient:red-blue red_blue1.png
60-40:
rr=`convert xc: -format "%[fx:0.6*255]" info:`
bb=`convert xc: -format "%[fx:0.4*255]" info:`
convert -size 200x600 gradient:"rgb($rr,0,$bb)-rgb(0,0,255)" red_blue2.png
Or perhaps this is what you want:
bb=`convert xc: -format "%[fx:0.1*255]" info:`
convert -size 200x600 gradient:"rgb(255,0,$bb)-rgb(0,0,255)" red_blue3.png
I have an Imagemagick bash shell script called, multigradient, which may do what you want. It allows you to create gradients of many colors each with stops to set where they start. For example:
multigradient -w 200 -h 600 -s "blue 0 red 80" -d to-top result.png
The first color must start at 0, but the direction can be many options. Here I go from bottom to top with pure blue at the bottom and pure red starting at 80 up from the bottom going to the top
(See)
I want to split an image on the basis of color of the line.
I'm using hough line detector to detect a line and mark it with red color.
Now,i want to split the image on the basis of line which has been overlayed using line detection algorithm.
Image with line detection overlay
i want to split the above image into two.
You can do that in Imagemagick with some Unix shell commands as follows. The basic idea is to average the image to one column, then search the column for the y coordinate of the red pixel. Then use that to crop the image into two parts.
INPUT:
width=$(convert -ping tRbWW.png -format "%w" info:)
height=$(convert -ping tRbWW.png -format "%h" info:)
y=$(convert tRbWW.png -alpha off -scale 1x! -fuzz 20% -fill red -opaque red txt:- | grep "red" | head -n 1 | cut -d: -f1 | cut -d, -f2)
height1=$((y+1))
height2=$((height-y+1))
convert tRbWW.png \
\( -clone 0 -gravity north -crop ${width}x${height1}+0+0 +repage +write top.png \) \
\( -clone 0 -gravity south -crop ${width}x${height2}+0+0 +repage +write bottom.png \) \
null:
Top:
Bottom:
I can get the 10 most frequent colors from an image with this command
convert MYIMAG.JPG +dither -colors 10 -unique-colors
The output is the following:
# ImageMagick pixel enumeration: 10,1,65535,srgb
0,0: (17797.7,15058.3,10214.1) #453B28 srgb(69,59,40)
1,0: (26745.1,24530.8,20814.7) #685F51 srgb(104,95,81)
2,0: (35510.4,30224.2,23717.1) #8A765C srgb(138,118,92)
3,0: (33428.3,32608.7,27562.4) #827F6B srgb(130,127,107)
4,0: (42221,36875.3,29255.8) #A48F72 srgb(164,143,114)
5,0: (53896.7,44085.9,24988.3) #D2AC61 srgb(210,172,97)
6,0: (45384.3,42509,38801.6) #B1A597 srgb(177,165,151)
7,0: (54519.7,46803.7,37705.7) #D4B693 srgb(212,182,147)
8,0: (56368.6,48645.3,40350) #DBBD9D srgb(219,189,157)
9,0: (58605,50733.4,41256.9) #E4C5A1 srgb(228,197,161)
Now I would like to either convert that or simply just get it in the following format:
#453B28
#685F51
#8A765C
#827F6B
#A48F72
#D2AC61
#B1A597
#D4B693
#DBBD9D
#E4C5A1
Is there a way to just get the hex values without the Rest ?
Thank you
convert ... | tail -n +2 | awk '{ print $3 }'
Use tail to skip the undesired first line of output.
Then use a simple awk program to keep just the 3rd column.
If you only have 10 colours. you may be prepared to put up with this awkwardness:
convert -size 10x1 gradient: -depth 8 -format "%[hex:p{0,0}]\n%[hex:p{1,0}]\n%[hex:p{2,0}]\n%[hex:p{3,0}]\n%[hex:p{4,0}]\n%[hex:p{5,0}]\n%[hex:p{6,0}]\n%[hex:p{7,0}]\n%[hex:p{8,0}]\n%[hex:p{9,0}]\n" info:
FFFFFF
E3E3E3
C6C6C6
AAAAAA
8E8E8E
717171
555555
393939
1C1C1C
000000
Other than that, I don't know of a native way to do as you ask, and Jonathon's method is as good as any. Another option may be like this, where I create a little image with a red, green, blue and white pixel then dump it as RGB and use xxd to format it in columns of 3 for R,G,B:
convert xc:red xc:lime xc:blue xc:white +append -depth 8 rgb: | xxd -p -c3
ff0000 # red
00ff00 # green
0000ff # blue
ffffff # white
I added the colour names for clarification - they don't actually come out of the process.
I have ~200 scanned photos which I want to crop the white space out of. See example:
Can someone provide me with the appropriate command line code to do this?... I have been trying to sort out the -trim and -fuzz options with no luck. NOT ALL images are same size (i.e. 4x6, 5x7, etc). All images were scanned/saved as jpg
Ideal scenario is a script where new trimmed photos are saved in one subdirectory.
Thanks in advance!
I would suggest using -morphology to remove the scan artifacts, trim, and then capture the resulting paging.
PAGE_OFFSET=$(convert TrmkF.jpg -morphology Dilate:3 Diamond:3,5 -fuzz 10% -trim -format '%wx%h%O' info:-)
The $PAGE_OFFSET variable should now have the rough location of the scanned photo. We can apply that value with the -crop command.
convert TrmkF.jpg -crop $PAGE_OFFSET output.jpg
[![output][1]][1]
Edit
A (powershell) batch script may look as simple as...
Get-ChildItem "C:\path\to\photos" -Filter *.jpg |
Foreach-Object {
$pageOffset = magick $_.FullName -morphology Dilate:3 Diamond:3,5 -fuzz 10% -trim -format '%xx%h%O' info:- | Out-String
$output = $_.FullName + ".output.jpg"
magick $_.FullName -crop $pageOffset +repage $output
}
ymmv
[1]: https://i.stack.imgur.com/u8bSs.png
I've found that the above gives bad results, I think the formatting is different on MacOS or something so sharing the success story here. I have exactly this same issue - hundreds of scanned photos with some blotches in the white ruining the auto trim function.
I just modified parameters from the other individual's answer and got amazing results using this:
cd into your folder of images
mkdir ../done
v
echo "$f";\
size=$(magick "$f" -bordercolor White -border 10x10 \
-morphology Dilate:5 Diamond:5,7 -fuzz 5% -trim \
-format "%wx%h%O" info:-); \
echo $size; \
magick "$f" -bordercolor White -border 10x10 -crop $size +repage "../done/$f"; done;