It sounds harder than it really is, and I can program this, though I'm searching for shortcuts.
I have a transparent PNG, with the dimensions of 250x525 pixels. Inside is a character that can be customized by my users, thus the dimensions of the real content inside that 250x525 image can vary. I want to reduce the 250x525 image down to just the avatar, by detecting where the first pixel begins vertically and horizontally, and where the last pixel ends.
Is there a shortcut for this? A function, or another way to do it perhaps? An example of an image I'd like to apply this to: http://i.troll.ws/92f2db20.png - imagine a box around the character. I want to calculate an invisible box around it, and pull the character out of it into its own image resource in GD.
The Reason: I have a function that can take an image and scale it to fit a larger image. I want to apply this to these characters, and first need to dumb it down to just the character.
Not GD, but Imagemagick/Imagick is able to do that vith the trimImage method.
$im = new Imagick("http://i.troll.ws/92f2db20.png");
$im->trimImage(0);
$im->writeImage('image.png');
Related
Overview:
I am working on a video creation project. The technology I am using are: imageMagick, php, ffmpeg.
Current Status:
Currently the project is able to create videos using images and texts and few basic transitions. The way I am doing it is using imagemagick to create gif using input images(with transition effects in them) and then converting all gifs to videos and atlast concatenating the video together.
Next Move (My question):
I am now set to take it to the next level. So, what I am having is a video(1920x1080) with some white frames(1280x720) that keeps shifting in each frame. I want to replace those white frames appearing in some frames of the video with some images(1280x720) that I wish to use. Please see the image here and you will get an idea: These are just two frames from my video. If you can see carefully the images are shifting(white space is not constant).
Expectation:
So, I want to fill those white space with one of my own image. If the case would have been for only one frame I could have used ffmpeg to overlay image on the exact width and height. But here the white space is not fixed and keeps shifting in all the frames and there are a lot of frames. So, I am looking for something like opencv or some other technology that can be used for object detection in a video or in a set of frames and replace the detected area with some other image.
I just need a kick. So, if anyone has already worked on something like this just suggest me what technology can I use. Thanks in advance.
It all depends on exactly what you can assume :
If you can safely assume that your rectangle's boundary is never occluded (hidden) somehow, you can try finding the edges in your image (like OpenCV's Canny edge) and then look for rectangular shape (corners forming a warped rectangle, or the very popular Hough Lines).
If the rectangle you're looking for is always white, you can threshold the image in a colorspace like HSV to look for maximum value (the V in HSV ~ brightness) then rectangular shape search in a binary image.
If your corners are occluded sometimes you'll have to do some tweaking with your image, like morphological operations ("grow and contract" binary thresholded image), then Hough Lines could do the trick.
Note that this answer assumes that once you know where the rectangle is, "you're done", and you just have to overwrite the rectangle with custom content.
I also do not check for any time-continuity : you video frame might jump around based on the frame-by-frame appearance of rectangle. You'd have to include some knowledge about previous positions.
I have a library of like 1 million images, and roughly half of these are watermarked with the same, half transparent watermark in the same spot.
Where do I begin, detecting the images with the watermarks? Is there some standard tools for this purpose?
If according to your question, you just want to detect the images that are watermarked, you can use the following algorithm:
Extract a sample of the watermarking image Scan the watermark image
pixel by pixel and store the first pixels in an array. Scan each
image pixel by pixel and store in an array. Whenever a row matrix
from the image being scanned contains elements of the array in the
same order, it's most likely a match.
The code could be something like this:
$no_of_pixels = what_you_got;
$matched = 0;
$thumbpixels = array();
$wmark = imagecreatefrompng("watermark.png");
list($width, $height) = getimagesize("watermark.png");
$tesimage = imagecreatefrompng("test.png");
for($h = 0; $h < $height; $h++){
for($w = 0; $w < $width; $w++){
if(imagecolorsforindex($testimage, imagecolorat($testimage, $w, $h)) == $thumbpixels[0]){
while($thumbpixels[$i++] === imagecolorsforindex($tesimage, imagecolorat($wmark, $w, $h)) && $no_of_pixels != $matched){
$matched++;
}
if($matched == $no_of_pixels) echo "Voila, we found it!";
}
}
}
EDIT
Just seeing your thumbnail example. If you just want to detect text, you can try tesseract-ocr or PhpOCR.
You may also consider PHPSane
Detecting almost any feature in an image is called Object Detection. There is a widely used libray called OpenCV. It has a very simple SDK, although setting up can be a real pain. It is well supported for C/C++ and (nearly well supported for) Python. It took me arnd 3 weeks to train my own Classfier (training), first time I started using OpenCV.
But I would not really depend on this solution entirely and consider my priorities. Also, it is very hard to achieve good rate with custom classifier. Other methods are more time consuming.
In short, not with complete accuracy.
At best, you could only apply heuristics on the image to see if it matches an exact watermark, and get a confidence rating -- for example, if the watermark if a 50% white overlay, then a scene that was predominantly white could give a false positive, and of course the inverse is true.
There are also problems that could arise if the images use a lossy compression, such as JPEG, as the edges, and the saturation may result in a watermark that isn't as saturated as expected, or as exactly positioned as expected.
Because you know where the watermark always is it is possible that you could use imagecolorat and imagecolorsforindex to get the alpha value for pixels both inside and outside of the watermark. I would expect the alpha values to be similar when there is no watermark, and different when there is (within some threshold that you would need to determine). Of course, this may not work on all images so if you need 100% accuracy you would probably need something more reliable.
In your case, where you are looking for the same logo in a predictable location, it is relatively simple. However it's much, much simpler and faster (as per my comment elsewhere) to match a copyright notice in the meta data!
A watermark is not going to produce fixed changes to the content - each modified pixel will obtain a new value based on the watermark and the image itself. Hence you need to extract this information - I'd go with diferentiating the image and just looking at the magnitude of the derivative (not the phase).
Then it's simply a matter of correlating the differential with one of just the watermark (or lots with the watermark and other content).
You really don't want to be doing this kind of image processing in PHP unless you're happy writing your own extensions. Most image processing toolkits will support differentiation and correlation.
BTW: if you don't know how to differentiate an image, and/or can't understand how to correlate an image, please don't ask - this is not the right forum for that discussion
Well if there is no tool to do this, you could try the following:
identify where the watermark appears as a percentage of pixels, eg bottom right 40px x 100px
For each image, make a temp copy and crop out the location of where the watermark would appear. This should leave both the watermarked version and the non watermarked version as the same
compare the images - e.g. combination of width x height, filesize, CRC or actual pixel comparison, though for a million images you'd need some serious CPU power.
I'm currently struggling with different resolutions when building my gallery-application. I've realized the problem: the photos can be in entierly different resolutions, or taken in landscape/portrait.
If I force the images to a fixed resolution - they are likely to be viewed as stretched.
If I don't: I can expect something like this (example of 6 different images with loose resolution, only fixed witdh):
When I'm actually looking for something like this (6 images with same resolution):
(these two galleries are actually running the same code)
I'd appreciate any suggestions on how to make this as pain-free as possible for the viewer. Thanks!
If you care anything about the artistic minded photographer, don't crop the image.
Resize them to a max-size (either width or height) to a specific measure, 400px, and place them each in a square div.
I think you're talking about image dimensions (not resolution, which is number of pixels in 1 inch).
To get th thing you want:
(1) Choose a width-height ratio that you want to show the image
(2) Cut of the extra portions of images to fit the ratio above (u can use GD library for PHP)
For example:
To make all portrait photos become landscape photos, cut off the top and the bottom sides. Rotating the portrait photos to become landscape is also a solution, but this won't be nice to viewers, coz they'll have to twist their necks to see the photos.
If you do not want to cut anything off, but still want to have as little whitespace on the screen as possible, you need to find an optimal arrangement of the images in unaltered form. This is a very difficult (NP-complete?) problem, but you can cut some corners if you want.
Looking at the images you posted, you could display five of them relatively cleanly together like this: put two portrait ones below each other, and add three landscape ones vertically stacked beside the portraits. If you scale them so that the height of two portraits is equal to the height of three landscapes, they will look more or less the same overall size.
You can find "pretty" screen-filling stacking methods for common aspect ratios of cameras, e.g. 16:9 and 4:3, and work off that assumption.
The gallery thumbnails have fixed dimensions (and fixed weight/height ratio), but source images have variable dimensions (and variable weight/height ratio). Here you have these options:
1- Stretch source images to thumbnail dimensions.
2- Add empty spaces (e.g. white) to the source images.
3- Crop extra spaces from the source images.
Demonstartion
I want to crop a rectangular image to a non-rectangular shape. I realize that if you take that completely literally, it's not possible. What I want to end up with is image X, cropped to shape Y, on a transparent background.
Let's say for example that I want to take a picture of the Idaho flag and crop it to the shape of the state of Idaho. I imagine I would do something like this:
Create an image that has opaque pixels for the shape of Idaho, transparent pixels everywhere else
Read and store some kind of bitmap for this Idaho state image
For each opaque pixel location in the Idaho state image, copy the corresponding pixel from the Idaho state flag image and place it on a blank, transparent canvas
Step 1 would obviously be done manually, but the rest would be done programatically. I think I have the right idea in general but I don't know how I'd approach the specifics. Can anyone point me in the right direction?
As far as implementation technology goes, I'm a PHP guy, so using gdLibrary or something that works with PHP would probably be the best way for me to go.
I would think it would be much easier to do by simply adding a bitmask or alpha channel. In that case you would use a negative mask image of your shape and then simply apply it to he regular image as a mask and then save out in a transparent format. Ive never actually done this with GD or ImageMagick but i would think its available as Jerry suggests.
Acutally here is a blog post form a similar SO question that might help: http://about.phalacee.com/geek/creating-mask-layers-using-php-gd
The usual way to do something like this would be to use white (all 1's) and black (all 0's) for your outline instead of transparent and opaque. Then you AND that image with the image you're trying to crop. The result is 0's where the outline image had 0's, and the other image where the outline had 1's.
You may also need to invert your outline image, and AND the inverted version with the background image. Then you OR the background image with the foreground image to produce a composite of the foreground image in the shape of Idaho (to use your example) and the background image everywhere else.
Depending on the capabilities of the library you're using, there's a good chance that kind of capability is directly available though. Just for example, Windows has this capability in the MaskBlt function.
In php using ImageMagick is probably your best bet:
$source = IMagick("sourcefile");
$mask = IMagick("maskfile");
$mask->adaptiveResizeImage($source->getImageWidth(), $source->getImageHeight(), true);
$source->compositeImage($mask, imagick::COMPOSITE_MULTIPLY, 0, 0);
$source->writeImage("newfile");
$source->clear();
$source->destroy();
sourcefile must be the source image as you like, maskfile must be a mask file that has the alpha channel set correctly for the shape you want.
I don't know if this is even possible with PHP, but I figured if it is, someone here will know how. I'm currently working on a project where users can customize a full body main avatar to be used throughout the site. There are a bunch of different face, hair, etc transparent png images that can be selected to make their custom avatar. I have this working great, but here is the hard part. I want to be able to use the face, hair, and beard (if male), and automatically create an 80x80 image that will be used as their small avatar for forum posts, etc.
There are a few obstacles with this. First, all of the images are 187x404 (big amounts of the image are transparent, the character body image is achieved by stacking the images, so a face image isn't actually that big). For this to work, the images would effectively have to be automatically cropped so that all of the extra space was removed and the actual face, hair, or beard part showed in the 80x80 spot.
The second issue is that some of the hair or beards (when placed on the full-size face image) would extend past the 80x80 and be chopped off. So the image would have to be pieced together at full size, and then resized to fit in 80x80.
I know the basic way of combining the 3 images into one (Combine 2-3 transparent PNG images on top of each other with PHP), but that is as far as I've gotten. If I'm crazy and this isn't possible then tell me. I'm probably way overcomplicating this, so if you see and obviously easier way to achieving this, I would love to hear it.
I think you need to decide first, cropping, resizing or a combination of both (cropping to a bigger square and resizing that).
Anyway, if you already have the images combined into one, all three options are easy to do in php. Take a look at imagecopyresampled().
The easiest way is just to always fit the face/hair/beard in the same area of the image. Then just crop that area out.
If you must, you can store extra data for each image specifying a rectangle in the image that must be visible in the small avatar. Then take the maximum extremities of these rectangles in all the images you compose, and crop+shrink that down to your small avatar size.
However, be aware that resizing PNG images by a few pixels (e.g. 83x83 -> 80x80) can substantially reduce the quality, particularly for images with lots of defined edges. This is because there are many pixels in the new image that are [nearly] evenly split between 4 pixels from the original image, and in images with sharp edges this leads to blurring.
So, shrinking an image to fit a portrait is not just difficult but also reduces quality. I'd cut off the beard instead!
I may be oversimplifying this, but can you try:
Keep track of max face size dimensions pre-compositing.
Output the composite image to a temporary file.
Crop square of largest values from step 1
Resize cropped image portion to 80 x 80