ImageMagick - rounding the alpha channel - imagemagick

I have an image which is white on a transparent background, but the white has some alpha channel around the object's edges (due to anti-aliasing). How could I make this pure white-on-transparent, by rounding the alpha channel so > 0.5 becomes white and <= 0.5 becomes transparent?

You need to threshold the alpha (transparency) channel at 50% thereby forcing all transparencies under 50% to zero and transparencies over 50% to 100%. Like this:
convert image.png -channel alpha -threshold 50% out.png

Related

Imagemagick - Inverse

I've a png image containing transparent pixels and colored pixels (mainly white).
I'd like to transform all transparent pixels to white pixels and all white pixels to transparent pixels within a given rectangle.
My idea would be to
convert the white pixels to red
the transparent colors to white
and the red colors to transparent
. Here' s my code:
1) convert ldl_0.png -fuzz 10% -fill red -opaque white lx.png
2) convert lx.png -background white -alpha remove -alpha off lx2.png
However I can' t figure out how do I transform red colors to transparent. How do I do that?
Also how can I force to do this only within a given rectangle?
Thank You.
-----
Try this in ImageMagick. Negate the alpha channel and turn the whole RGB channels to white.
convert in.png -channel a -negate +channel -fill white -colorize 100 out.png

ImageMagick Unable to change colour in shade explicitly for image

I want to use ImageMagick to change colour in shade.
I am able to manage the shade change using :
convert input.png -colorspace HCL -channel R -evaluate set 5% +channel -colorspace sRGB output.png
Using set XX% i am able to get different colours like, red, green, yellow, blue, pink, sky-blue, gray, etc.
The below command works for targeting blue colour :
convert input.png -colorspace HCL -channel R -separate +channel -level 48,52% output.png
But I am unable to target other colour explicitly.
For example, if I want to change green colour with some other colour, resulted image will effect green, yellow,red and sky-blue as well.
Is there a way to explicitly change a single colour in shade for :
yellow
sky-blue
pink
green
white
black
red
I tried changing all -channel : R,G,B,C,M,Y,K,A,O.
Using -separate option I can target RBG, but the problem with RGB is R effect red, yellow and pink, G effect green, sky-blue and yellow and B effect blue, pink and Sky-blue.
sample for output :
RGB image colour change
expected output : In the above output for "output-0" it effect red,yellow and pink. i want the command which will effect only red. similarly for other colours as well.
links I used : https://www.imagemagick.org/discourse-server/viewtopic.php?t=33361
I am using python to run this command. I am also open to use other libraries which will work with all the colours explicitly.
If your image is representative like I requested, it is as simple as this:
magick rgb.png -fill white -opaque red result.png
If you also want to affect hues "close to red", you can apply some fuzz:
magick rgb.png -fuzz 40% -fill white -opaque red result.png
Notice that also affects the edges of the red circle where it is a "feathered red".
If not, your ImageMagick code is essentially doing a "Hue rotation" and, as you have noticed, it affects the entire image. Read the Wikipedia page on HSV before continuing. Here is an HSI Hue wheel for reference:
The solution is to do your Hue rotation, but apply its effects via a mask that only selects the colours/areas you want affected. Remember that OpenCV halves the Hue from the range 0..360 to 0..180 so that it can store a Hue in a np.uint8.
So, if we load the same image as above and select only the greens (where Hue is near 120) we can rotate just those into blues by adding 60 (Hue=240):
#!/usr/local/bin/python3
import cv2 as cv
import numpy as np
# Load the image and convert to HSV colourspace
image = cv.imread("rgb.png")
# Convert to HSV and split channels
hsv=cv.cvtColor(image,cv.COLOR_BGR2HSV)
H,S,V = cv.split(hsv)
# Shift only greens (Hue near 120) around hue circle by 120 degrees to blues - remembering OpenCV halves all these values - see comment
H[(H>55)&(H<65)] += 60
# Recombine into single 3-channel image and convert back to RGB
result = cv.merge((H,S,V))
result = cv.cvtColor(result,cv.COLOR_HSV2BGR)
cv.imwrite("result.png",result)
If you want to change the blues (Hue=240) into yellows (Hue=60), just change this:
H[(H>55)&(H<65)] += 60
into this:
H[(H>115)&(H<125)] -= 90
If you want to broaden the range of greens affected, decrease the 55 in my code and/or increase the 65. If you want to move greens to a different hue, either increase or decrease the 60.
You can do all the stuff above with PIL/Pillow if you want to - you don't need to install the (massive) OpenCV.
Keywords: Image, image processing, Python, OpenCV, ImageMagick, Hue, HSL, HSV, hue rotation, colour replacement, selective colour, mask.

Does the position of the pixels in an image govern the edge detection?

Referring this video by andrew ng
https://youtu.be/XuD4C8vJzEQ?list=PLkDaE6sCZn6Gl29AoE31iwdVwSG-KnDzF
From this video I conclude that for detecting vertical edges in an image there should be some BRIGHTER followed by DARKER regions starting from the left side, then only this [[1,0,-1],[1,0,-1],[1,0,-1]] will act as a vertical edge detector otherwise not.
Is my conclusion correct ?
and
Is the vice versa will also be true ?
If you think about the filter:
1 0 -1
1 0 -1
1 0 -1
you will see that it is just subtracting the pixels to the right from the pixels to the left at each location, i.e. finding the horizontal differences.
As such, it is capable of finding transitions from light to dark and dark to light, it's just that the differences will show up with an opposite sign (plus or minus). So, if you transition from a bright area on the left to a darker area on the right, you will have a large number (bright) minus a small number (dark) and the difference will be positive. Conversely, if you transition from a dark area on the left (small number) to a brighter area on the right (large number), you will end up with a negative difference.
Here is an example, just done in Terminal with ImageMagick. Start with this image:
Apply the filter you are talking about:
magick input.png -morphology convolve '3x3: 1,0,-1 1,0,-1 1,0,-1' result.png
And you can see it finds only dark-to-light edges.
If you want to detect edges from light to dark and dark to light, you need to either:
use a signed number (as opposed to unsigned) so you can hold negative results, or
add a "bias" to your convolution.
If your data was unsigned 8-bit, you could add a 50% bias by dividing all your current values by 2 and adding 127 before convolving, for example.
So, applying a bias, your filter now finds dark-to-light and light-to-dark edges:
magick input.png -define convolve:scale='50%!' -bias 50% -morphology convolve '3x3: 1,0,-1 1,0,-1 1,0,-1' result.png
If you now want to detect horizontal edges transitioning from light-to-dark, rotate the filter to this:
-1 -1 -1
0 0 0
1 1 1
And apply:
magick input.png -morphology convolve '3x3: -1,-1,-1 0,0,0 1,1,1' result.png
Or, if you want to find horizontal edges transitioning from dark-to-light, use:
1 1 1
0 0 0
-1 -1 -1
magick input.png -morphology convolve '3x3: 1,1,1 0,0,0 -1,-1,-1' result.png
And the same again, but with a bias so we can find both light-to-dark and dark-to-light transitions in one fell swoop:
magick image.png -define convolve:scale='50%!' -bias 50% -morphology convolve '3x3: -1,-1,-1 0,0,0 1,1,1' result.png
Anthony Thyssen provides more excellent information about convolution than you could ever hope to need in a very approachable style here.

Set alpha according to gradient with imagemagick

Is it possible to set the alpha channel of an image according to a gradient with ImageMagick?
I'd like the pixels on the left border of an image to be 100% transparent, and the ones on the right border to be 100% opaque, and with the ones in the middle having progressively lower transparency values.
Or in a more general case - given a grayscale image, set the alpha channel of another image as a function of the B&W values (black = 100% alpha, white 0% alpha).
With ImageMagick you can use -sparse-color to apply a gradient only to the alpha channel to get the result you describe.
convert in.png -alpha set -background none -channel A \
-sparse-color barycentric "0,0 none %[w],0 white" +channel out.png
That command starts by activating the alpha channel and setting the background color to transparent. Then it uses -channel A to apply the following operation only to the alpha channel. The -sparse-color operation tells it to start with transparent at the far left edge, pixel 0,0 and graduate to opaque at pixel %[w],0. The %[w] means the width or far right edge.
Although there are many ways to accomplish the effect you've described, by using -sparse-color you can easily make the gradient start and end at any positions on the image without having to create any intermediate masking images.
Simple. You would use -composite CopyOpacity to set the alpha channel from a gradient mask.
Given I have the following images. image.png & transparent_mask.png
We can set the image transparency (where black is alpha, and white is opaque) by copying values from the mask image to the input image alpha channel.
convert image.png transparent_mask.png -compose CopyOpacity -composite output.png

Creating a more effective matt for chromakey?

I'm trying to chromakey some pictures. Here is an example of one:
Here is another one,
Now using image magic, I can generate a mat like this..
But I can never get the mat to be "full". My plan is to create a static mat for the turntable and the lightbank -- those won't have to be removed. But, I'd like to fix the problems I'm seeing with the grill, licenseplate, and window. I'd like the car to show up pitch-black. I'm using ImageMagick's convert to get this working,
convert 1.bmp -channel g -separate +channel -fuzz 45% -fill black -opaque black -fill white +opaque black greenscreensample_mask_1.gif
How can I improve this to fill in the bumper of the vehicle?
I would guess the shinny parts are slightly green and you could try reducing the fuzz value.
You can use the -fx operator and then work with specific channels. The following is by no means optimal, and also, it is very inefficient to execute:
convert ./in.jpg -background none -transparent white -channel Alpha -fx '1-((g-r)+(g-b)+(g-(r+b)/2))^2' -channel Green -fx '(r+b)/2' ./out.png;eog ./out.png
in order to obtain a key for the green channel you can subtract the
red from the green
blue from green
average of blue and red channels from the green channels
the very basic colour correction involves replacing fringed areas with the average of the blue and red channels, here however the entire image had its green channel replaced with the average of the blue and red channels. you should actually write an algorithm that seperates the fringe into a seperate channel, then you colour correct the entire image and mix it in with the original based on this "fringe" matt.
thankyou, best of luck

Resources