I have a problem with getting fine contour of the image.
How to do it with PHP Imagick?
Input image: Imagick wizard
Plan #1 Outline
Get image with (more/less) clear, consistent background (for example: white, red or transparent)
Remove background if it is set
Add outline (specific color)
Remove image inside
Result: http://i57.tinypic.com/2wg91qx.png
Plan #2 Sketch
Get image with (more/less) clear, consistent background (for example: white, red or transparent)
Remove background if it is set
Add sketch effect
Remove image inside
Result: http://i60.tinypic.com/az9vr5.png
PS:
borders and/or shadows didnt' work for me well
There are many ways to outline a picture. Here's one of them that does more or less what you wanted. Note that wizard's picture requires some extra processing. First background isn't fully white (it has some #FEFEFE or alike pixels). Also what is more troubling the upper part of the desk is filled with pure white. So you can either use white pixels after blurring as background (my way) or try to flood fill from the corner with matteFloodfillImage(). However this may leave space between desk legs not transparent.
function drawImage(Imagick $i)
{
$i->setImageFormat("png");
header("Content-Type: image/" . $i->getImageFormat());
echo $i;
exit;
}
$o = new Imagick('wizard.png');
$o->setImageBackgroundColor('white'); // handle tranparent images
$o = $o->flattenImages(); // flatten after setting background
$o->blurImage(5, 30);
$o->whiteThresholdImage( "#F8F8F8" );
$o->blackThresholdImage( "#FFFFFF" );
$o->edgeImage(5);
$o->negateImage(false);
$o->paintTransparentImage($o->getImagePixelColor(0, 0), 0, 2000);
$o->colorizeImage("red", 1);
drawImage($o);
Sketching is a little more complex and I would recommend further reading on IM capabilities http://www.imagemagick.org/Usage/photos/#color-in
Related
I have a project I'm working on right now... I want to know is there any idea how i can make an app that every time i upload a photo it, with the specific size it cut like the middle part only and puts it on another photo i chose.
here is an example : 1 - Upload man photo with white background 2- it takes the middle part of the photo 3 - i upload a garden photo and the man shows there.
I just need to know the way to make it.
Is there also a way to delete white backgrounds like Chrom key or something?
example
Look into ImageMagick
ImageMagick allows you to cut, crop, colorize, etc. For example, here is some sample code showing how to crop a photo:
<?php
function cropImage($imagePath, $startX, $startY, $width, $height) {
$imagick = new \Imagick(realpath($imagePath));
$imagick->cropImage($width, $height, $startX, $startY);
header("Content-Type: image/jpg");
echo $imagick->getImageBlob();
}
?>
A brief scan of questions regarding ImageMagick and PHP will be helpful:
https://stackoverflow.com/questions/tagged/imagemagick+php
Resources:
https://phpimagick.com/
ImageMagick options and settings
Using ImageMagick to crop from center with PHP
I got this code to do that:
$im = new Imagick("test.jpg");
$im->paintTransparentImage($im->getImageBackgroundColor(), 0, 500);
$im->setImageFormat('png');
$im->writeImage('finish.png');
And this is the result (I added manually pink background to see the problems better):
When I increase the fuzz then more white pixels disappear next to the object but then more white pixels also disappear inside the object.
I tried the same image on a website and the result there is:
Which is pretty perfect. Does someone know how to do that?
In case someone need the original image for testing:
UPDATE:
Adding $im->despeckleimage(); before $im->paintTransparentImage makes a better result:
The only thing needs to be done is fill fill the small empty areas with white pixels. Is there any way to do that?
I obtained an instant solution using the GrabCut Algorithm. I used OpenCV 3 with python to get your desired output. Unfortunately I do not know php nor do I know imagik.
CODE:
import numpy as np
import cv2
img = cv2.imread('Dress.jpg',1)
cv2..imshow('Original image',img)
mask = np.zeros(img.shape[:2],np.uint8)
bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)
rect = (60,20,325,503)
cv2.grabCut(img,mask,rect,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)
mask2 = np.where((mask==2)|(mask==0),0,1).astype('uint8')
nimg = img*mask2[:,:,np.newaxis]
cv2.imshow("Extracted image",nimg)
cv2.waitKey()
cv2.destroyAllWindows()
I first created a black background using the mask variable.
This is what I obtained.
Visit THIS PAGE for details of this algorithm and the parameters used. You can work this out for masking on a colored background also.
I beleive the same can be tried out with imagik also. Hope this helps :)
EDIT:
This is in response to the edit you made to the question.
The following was the image uploaded by you:
I applied threshold and obtained the following image:
Now I performed 'morphological closing' operation and obtained this:
Finally I masked the image above with the original image you uploaded in the beginning to obtain this:
I am using imagemagick to crop an image (using the PHP interface, but i don't think that matters too much).
I wish to crop an image, but if the crop portion goes over the image, I want it to show a background colour.
Here is the code I have so far:
$newImg = new Imagick($imgUrl);
$newImg->cropImage($cropW, $cropH, $x, $y);
$newImg->resizeImage($resizedW, $resizedH, Imagick::FILTER_CATROM, 1);
$newImg->writeImage($output_filename);
However for some reason, imagemagick refuses to show any portion of the image that is further than boundary of the image (i.e. if x and y is larger than the original image width and height, it pushes it down into view of the image).
e.g.
I want it so that if x and y is beyond the image portion, it shows a background color instead. Thanks!
UPDATE
Thanks to namelivia suggestion I decided to use the "extent" tool.However I am unable to set a background colour using this tool through PHP. For example, the following produces a larger image but with a black background, NOT purple.
$newImg = new Imagick($imgUrl);
$newImg->setImageBackgroundColor('#e7609a'); //Doesn't return an error (i.e. returns true) but also does not work!
$newImg->setImageExtent(2000, 2000);
$newImg->writeImage($output_filename);
UPDATE 2
Seems like you should use extentImage (NOT setImageExtent) if you wish to use a background color.
I think you should use the extent option first, using extent you can also pick a background color for the area "behind" then you can crop the extended image.
I have the last few hours tried to get a PNG logo with a transparent background on top of a JPG background. I have tried several ways and with several globals as well, but I do not seem to be able to get the result I want.
"First Attempt":
$overlay = new Imagick('overlay.png');
$image = new Imagick('background.jpg');
$image->compositeImage($overlay, Imagick::COMPOSITE_DEFAULT, 10, 10);
$image->writeImage('background.jpg'); //replace original background
$overlay->destroy();
$image->destroy();
As you can see, the Jaguar logo is all black.
"Second Attempt"
$overlay = new Imagick('overlay.png');
$image = new Imagick('background.jpg');
$image->setImageColorspace($overlay->getImageColorspace() );
$image->compositeImage($overlay, Imagick::COMPOSITE_DEFAULT, 10, 10);
$image->writeImage('background.jpg'); //replace original background
$overlay->destroy();
$image->destroy();
This one the Jaguar logo looks like it should, but the background is all messed up now.
I have tried with Imagick::setImageMatte and tried to add the overlay to a white background (thought I does need to have a transparent background) and still it won't display the image properly. I have tried many other variations of the 2 above snippets but they all seem to make the PNG completely or partial black.
What am I missing or doing wrong? Can anyone give me a nudge in the right direction?
Please note this needs to be done in PHP.
Thank you very much!
I am a huge idiot! Turns out I forgot to convert the images from CMYK to RGB.
For anyone who might encounter this in the future, learn from my incompetence!
I was trying to overlay a png with transparency over the top of another png. I used this line from the PHP docs.
$src1->compositeImage($src2, Imagick::COMPOSITE_MATHEMATICS, 0, 0);
but I was getting the same problem. The overlay came through as black only. Changing it to this seemed to fix the colours.
$src1->compositeImage($src2, Imagick::COMPOSITE_DEFAULT, 0, 0);
On a Magento site, I’m just uploading one picture per product, and using that as the base, small and thumbnail images. However, my pictures aren’t square, so I’m getting a black background added to the thumbnail that’s created. Any ideas how to change that to a white background?
http://www.magentocommerce.com/?ACT=25&fid=10&aid=10785_osKeOnfKFLFvgqVYbr0j&board_id=1
I’ve searched for this but can’t find a decent answer anywhere…
I found a workaround for this. The side effect is that the class used for image resize will fill all images with white (even transparent ones), but this doesn't realy affect Magento since it doesn't use transparent fill anyway. So to solve the issue do this:
Go to lib\Varien\Image\Adapter\Gd2.php in your magento folder
Find this line
$this->_fillBackgroundColor($newImage);
and replace it with this line
$this->_fillBackgroundColor($newImage,$frameWidth,$frameWidth);
Find this line
private function _fillBackgroundColor(&$imageResourceTo)
and replace it with this
private function _fillBackgroundColor(&$imageResourceTo,$w,$h)
Find this code
if (!imagefill($imageResourceTo, 0, 0, $color)) {
throw new Exception("Failed to fill image background with color {$r} {$g} {$b}.");
}
and replace it with this
imagefilledrectangle($imageResourceTo,0,0,$w,$h,$color);
That is it. The problem comes from the PHP function imagefill in Gd2 not working on some setings. This is a workaround using imagefilledrectangle, and worked for me. Hope it solves your problem too.
Correction on point 4 from Adi's answer:
4. Find this code
if (!imagefill($imageResourceTo, 0, 0, $color)) { throw new Exception("Failed to fill image background with color {$r} {$g} {$b}."); }
and replace it with:
if (!imagefilledrectangle($imageResourceTo,0,0,$w,$h,$color)) {
throw new Exception("Failed to fill image background with color {$r} {$g} {$b}.");
Varien_Image which is used in Magento offers a possibility to set background color of scaled image. You can use similar code somewhere before outputting the image (resize method?) to make background white:
$image->backgroundColor(array(255, 255, 255));
Adi's answer led me in the right direction, but I was still getting a black line on my images. I discovered that when an image is cropped, Magento creates a canvas background, then the image on top of it. The canvas was producing the black line on my images.
I managed to fix it by adding Adi's changes, and then additionally, in the crop() function (in the same file), I added:
list($r, $g, $b) = $this->_backgroundColor;
$bg_color = imagecolorallocate($canvas, $r, $g, $b);
imagefill($canvas, 0, 0, $bg_color);
After the function (around line 554, after adi's changes):
imagecopyresampled
Now my images have the background colour they should have!
Another thing to note, instead of editing this file directly in the core, it should be copied to:
app/code/local/Varien/Image/Adapter/Gd2.php
Hope this helps someone struggling with the same issue.