I want to remove a area from a image but I am not sure where to look at.
Let me give you a example.
Source:
Destination:
So, I've removed 100x100 a area starting at 100x100 pixels.
Could someone please guide me where to look at?
I think you want to paint a white rectangle on an image. So if you want a white rectangle 100px wide and 20px tall, offset 10px from the left side and 20px from the top, use:
magick input.png -fill white -draw "rectangle 10,20 110,40" result.png
So, if I use a 200x100 magenta input image, I get:
Following on from the comments, here is an example if you have an image with no existing transparency:
And to "punch a transparent hole" we create a new layer the same size as the image, filled with white then draw a black hole in it, and push the result into the transparency layer of the original:
magick image.png \( +clone -fill white -colorize 100% -fill black -draw "rectangle 20,10 300,40" \) -alpha off -compose copy-alpha -composite result.png
If the original image already has transparency which we don't want to replace entirely, but just modify with an extra hole, we can start from this image:
And proceed to extract the original alpha channel, modify it and push it back into the original:
magick image.png \( +clone -alpha extract -fill black -draw "rectangle 10,40 80,80" \) -alpha off -compose copyalpha -composite result.png
I assume you want a transparent region. Here is how to do that in Imagemagick and Python/OpenCV.
Convert the image to include and opaque alpha channel. Then create a mask that is a white background with a black rectangle. White for where the result should be opaque and black where it should be transparent. Then put the mask into the alpha channel of the image.
Input:
Imagemagick
convert barbara3.jpg \( +clone -fill white -colorize 100 -fill black -draw "rectangle 50,50 250,150" \) -alpha off -compose copy_opacity -composite result.png
Python/OpenCV
import cv2
import numpy as np
# read image
img = cv2.imread('barbara3.jpg')
hh, ww = img.shape[:2]
# convert to image with opaque alpha channel
imgA = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
# create mask of filled black rectangle on white background
# white for opaque and black for transparent
mask = np.full((hh,ww), 255, dtype=np.uint8)
mask = cv2.rectangle(mask, (50,50), (250,150), 0, -1)
# put mask into alpha channel of image
result = imgA.copy()
result[:,:,3] = mask
cv2.imwrite('barbara3_mask.png', mask)
cv2.imwrite('barbara3_transparent_box.png', result)
cv2.imshow("img", img)
cv2.imshow("mask", mask)
cv2.imshow("result", result)
cv2.waitKey(0)
Mask:
Result:
Download the resulting image to see that it is transparent and not white.
Related
To demonstrate.
Original:
After ImageMagick:
I have some ideas:
Duplicate the image, crop the duplicate, then flatten the images together
Reverse mask?
Does anyone have any suggestions?
Although this has been successfully answered, I'll offer another simple approach using IMv6...
convert pasta.jpg -fill white \
\( +clone -evaluate set 25% -draw "roundrectangle 20,20 80,80 15,15" \) \
-compose multiply -composite result.png
After reading in the input image, in parentheses it clones the input and uses -evaluate to set the entire clone to 25% gray. A white "roundrectangle" is drawn on that gray image in the area you want to preserve. The mask looks like this...
Then after the parentheses, that mask and the input image are composited with -compose multiply. That leaves the white rectangle area as it was in the original input, and the rest of the image is multiplied by 0.25, leaving it darkened. The result...
This command should work just the same in IMv7 by changing "convert" to "magick". And it should work as well on Windows CLI by changing the continued-line backslashes "\" to carets "^", and removing any backslashes before the parentheses, so this "\(...\)" to this "(...)".
You can do that in Imagemagick by darkening the whole image, creating a round rectangle mask image, then composite the original with the darkened using the mask image.
Input:
convert pasta.jpg \
\( -clone 0 -brightness-contrast -75,0 \) \
\( -clone 0 -fill white -colorize 100 -fill black -draw "roundrectangle 20,20 80,80 15,15" -alpha off \) \
-compose over -composite \
pasta_rect.jpg
Result:
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
I am using Image Magick to overlay a dimmed caption to an image, with IM automatically choosing the best fontsize:
convert -background '#0008' -fill white -geometry +0+330 -size 370x60 caption:$title $image +swap -composite $imageOutput
My problem is that there is not enough space around the text, I would like to add some "padding". I usually do that with the -border option but if I add this to my command above, the caption is not dimmed anymore.
Do you have a solution to create a dimmed caption with enough room around the text?
I have a solution, but it's a bit of a kludge because I had trouble extending or bordering a semi-transparent background. In the end, I just constructed the caption on a black background and bordered it in black, then I tweaked the alpha channel afterwards:
convert -background black -bordercolor black -fill white \
-size 370x60 caption:"This is the title" \
-trim -border 20 -channel A -fx '(lightness/2)+.5' \
-geometry +0+200 background.gif +swap -composite result.png
The only tricky part is -channel A -fx .... The first part means that we are only affecting/modifying the alpha/opacity channel. The 0.5 means that all pixels become at least 50% opaque, and (lightness/2) means that absolutely white pixels, i.e. your lettering, (which will have a lightness of 1) become fully opaque because 0.5+(1/2) totals to one. The point of this is to preserve the anti-aliasing around the edges of the letters to some degree.
Using imagemagick, I want to clean the left side of an image, i.e. make white without cropping. For example cleaning the left-most vertical strip of 25 pixels wide. I figured out how to crop to a given geometry, but I couldn't figure out how to clean without cropping.
Here is my start image, made like this:
convert -size 256x256 gradient:cyan-yellow image.png
Method 1
One way to do it would be to use -fx and set all pixels where the x-coordinate is less than 25 to 1.0 (i.e. white) and leave all other pixels as they are:
convert image.png -fx "i<25?1:u" result.png
Method 2
Another, faster way to do it might be to clone the original image, and scale it down to 25 pixels wide, fill it with white and composite that over the original image:
convert image.png \
\( +clone -scale 25x! -fill white -colorize 100 \) \
-composite result.png
The result is the same.
Method 3
A third way to do it might be to crop the image 25 pixels in from the left side, then splice 25 white pixels back on the left side:
convert image.png -crop +25+0 -background white -gravity west -splice 25x result.png
Method 4
Bit of a kludge, but nearer to what you asked. Here, I guess that your image height doesn't exceed 10,000 pixels and draw a rectangle:
convert image.png -fill white -draw "rectangle 0,0 24,9999" result.png
I guess the proper way to do this is to get the height first then use it:
#!/bin/bash
h=$(convert image.png -format "%[fx:h-1]" info:)
convert image.png -fill white -draw "rectangle 0,0 24,$h" result.png
Here is my code:
#! /usr/bin/env sh
# Generate test image.
convert -size 100x60 xc:blue -fill blue -stroke black -draw "circle 50,30 55,55" in.png
# Make background transparent.
convert in.png -fill none -draw 'matte 0,0 floodfill' -flop -draw 'matte 0,0 floodfill' -flop out.png
# Replace transparent background with green.
mogrify -background green -flatten out.png
# The wrong way.
convert in.png -transparent blue oops.png
mogrify -background green -flatten oops.png
It is based on this snippet: https://snippets.aktagon.com/snippets/558-how-to-remove-a-background-with-imagemagick
Starting with this:
I want to get this:
Not this:
Can I achieve this with a single convert command instead of a convert followed by a mogrify?
I am using ImageMagick 6.8.9-9.
Essentially, you are seeking a "floodfill", like this:
convert in.png -fill green -draw 'color 0,0 floodfill' result.png
That will look at the top-left pixel (0,0) and fill all similarly coloured pixels which are connected to it with green. If your background has slight variations in it, e.g. it's a JPEG, add some fuzz factor
convert in.jpg -fuzz 25% ...
Note that if your circle had touched the top and bottom edges, it would prevent the fill from flooding around to the right side of the diagram. So, let's say you had created your circle like this:
convert -size 100x60 xc:blue -fill blue -stroke black -draw "circle 50,30 50,0" in.png
And then you run the above command, you will get:
If that happens, you can add a single pixel wide border all the way around for the colour to "flow" through first, then flood-fill, and finally remove it later:
convert in.png -bordercolor blue -border 1 -fill green -draw 'color 0,0 floodfill' -shave 1x1 result.png