I'm looking for the most optimal way of extracting single color on background and replace it with some picture on the fly in JavaCV. I wrote very simple method reading pixel by pixel and replacing it if the color is green for example.
This is very slow and even if I divided it into few threads it works dramatically slow.
This must be done on live so I have to find out some other method. Perhaps I will have to add some watermark as well after background replacing, so the application must be quite fast.
Does anybody can help me finding right way of doing it ?
I spend all day long trying to find other way of doing it, but.. all examples I have found doesn't work or maybe I do not know how to adopt them to my needs.
This guy (http://www.youtube.com/watch?v=WOEuE3D88b0) wrote that he is reading pixel by pixel - no way, or maybe he had very fast multi-core workstation. On my MacBook Pro 2.5 i5 it just doesn't work :(
I have used your example and I think that I have mixed it totally. I can see mask of moving me ( white on black background) and if I use CvCopy I can see background appearing at the places where white dots are.
Unfortunatelly his is not requested result, but I think I must be very close to it ;) I have to leave me and replace all static objects.
Could you please examine my code ?
private static final IplImage back = cvLoadImage("/Users/user/app/eclipse/JavaCV/resources/1.png", CV_LOAD_IMAGE_COLOR);
private static BackgroundSubtractorMOG2 bgs = new BackgroundSubtractorMOG2(30,16,false);
public static IplImage replacePixels2(IplImage img){
IplImage frame = cvCloneImage(img);
//bgs.getBackgroundImage(frame);
IplImage image = IplImage.create(frame.width(), frame.height(), IPL_DEPTH_8U,1);
bgs.apply(frame, image, -1);
IplROI roi = new IplROI();
roi.xOffset(0);
roi.yOffset(0);
roi.width(frame.width());
roi.height(frame.height());
IplImage backImageWithRoi = frame.roi(roi);
cvCopy(back, backImageWithRoi, image );
return backImageWithRoi;
}
I also tried grabCut but this is extremely slow and can't be used in changing stream on live :(
Best Regards
Jan
Since JavaCV is an interface to OpenCV, then you must be able to perform Grabcut segmentation.
As answered here too.
Related
I am working on a project where I want to detect the pores in a given skin image.
I have tried various methods(HoughCircles, BlobDetection and Contours) from OpenCv using Java, however, I am unable to proceed.
HoughCircles is showing me all false circles and same is the case with contours.
My current code uses blob detection technique which is also not showing what is required. Sample code is written below:
public void detectBlob() {
Mat orig = Highgui.imread("skin_pore.jpg",Highgui.IMREAD_GRAYSCALE);
Mat MatOut= new Mat();
FeatureDetector blobDetector;
blobDetector = FeatureDetector.create(FeatureDetector.SIFT);
MatOfKeyPoint keypoints1 = new MatOfKeyPoint();
blobDetector.detect(orig,keypoints1);
org.opencv.core.Scalar cores = new org.opencv.core.Scalar(0,0,255);
org.opencv.features2d.Features2d.drawKeypoints(orig,keypoints1,MatOut,cores,2);
Highgui.imwrite("PhotoOut.jpg", MatOut);
}
public static void main(String args[]) {
BlobDetection bd = new BlobDetection();
bd.detectBlob();
}
When I tried the same code using FeatureDetector.SIMPLEBLOB instead of FeatureDetector.SIFT it shows almost 0 blobs.
The output and source images are attached for the above code. Source Image
Output Image using SIFT
Is there any other algorithm which can help in achieving the result or what can be the appropriate approach to achieve this?
As you did not ask anything in your question I won't give you an answer. More some general advice.
That you tried to solve that problem using the named algorithms clearly shows that you have absolutely no clue what you are doing. You lack the very basics of image processing.
It's like trying to win vs decent chess player if you don't even know how the figures can move.
I highly recommend that you get yourself a beginners book, read it and make sure you understand its contents. Then do some more research on the algorithms you want to use, befor you use them.
You cannot take some arbitrary image, feed it into some random feature detection algorithm you find on the internet and expect to succeed.
Hough transform for cirles for example is good for finding circle shaped contours of a roughly known radius. If you know how it works internally you will know why it is not a good idea to use it on your image.
https://en.wikipedia.org/wiki/Circle_Hough_Transform
Blobdetection and contour based algorithms might work, but only after a lot of pre-processing. Your image is not very "segmentation-friendly"
https://en.wikipedia.org/wiki/Image_segmentation
https://en.wikipedia.org/wiki/Blob_detection
A SIFT detector usually has to be taught using reference images and reference keypoints. I don't see this either in your code.
https://en.wikipedia.org/wiki/Scale-invariant_feature_transform
Please note that reading those wikipedia articles will only give you a first idea of what's going on. You have to read a lot more.
Always start at the beginning of your processing chain. Can you get better images? (Better means more suitable for what you want to detect). This is like 10% camera and 90% illumination. I don't think detecting skin pores is a classical task for shitty cellphone pictures so why not put a bit effort into your imaging setup?
First rule of image processing: crap in = crap out. You should at least change the angle of illumination or even better approach like shape from shading.
An image optimized for the detection you have to do is cruicial. It will make image processing so much easier.
Then pre-processing: How can you transform the image you have into something you can easily extract features from?
And so on...
I need to to clip variablesized images into puzzle shaped pices like this(not squares): http://www.fernando.com.ar/jquery-puzzle/
I have considered the posibility of doing this with a php library like Cairo or GD, but have little to no experience with these librays, and see no immidiate soulution for creating a clipping mask dynamicaly scalable for different sized images.
I'm looking for guidance/tips on which serverside programing language to use to accomplish this task, and preferably an approach to this problem.
You can create an image using GD with the size of the puzzle piece. and then copy the full image on that image with the right cropping to get the right part of the image.
Then you can just dynamically color in every part of the piece you want to remove with a distinct color (eg #0f0) and then use imagecolorallocatealpha to make that color transparent. Do it for each piece and you have your server side image pieces.
However, if I where you I would create the clipping mask of each puzzle peace in advance in the distinct color. That would make two images per connection (one with the "circle" connecter sticking out and one where this circle connector fits into). That way you can just copy these masks onto the image to create nice edges quickly.
GD is quite complicated, I've heard very good things about Image Magick for which there is a PHP version and lots of documentation on php.net. However, not all web servers would have this installed by default.
http://www.php.net/manual/en/book.imagick.php
If you choose to do it using PHP with GD then the code here may help:
http://php.amnuts.com/index.php?do=view&id=15&file=class.imagemask.php
Essentially what you need to do with GD is to start with a mask at a particular size and then use the imagecopyresampled function to copy the mask image resource to a larger or smaller size. To see what I mean, check out the _getMaskImage method class shown at the url above. A working example of the output can be seen at:
http://php.amnuts.com/demos/image-mask/
The problem with doing it via GD, as far as I can tell, is that you need to do it a pixel at a time if you want to achieve varying opacity levels, so processing a large image could take a few seconds. With ImageMagick this may not be the case.
I'm currently developing my first Android app and am having some issues rendering images. The image itself is great quality to begin with, but upon rendering it the quality drastically lowers. Edges become jagged and it just looks poorly done. Everyone I've showed it to thus far has almost immediately noticed it, without any prompting about it. [start on left, end on right:]
I'm trying everything I am aware of and every tip I've been able to find by looking around online, but nothing seems to fix it.
Currently, I get the image as a Bitmap and scale it:
Bitmap holeImage = BitmapFactory.decodeResource(res, R.drawable.hole_image);
Bitmap holeImageBMP = Bitmap.createScaledBitmap(holeImage, width, height, true);
Once I have the image, I create a Paint, set a few smoothing attributes to true, and then draw it on the canvas:
Paint smoothingPaint = new Paint();
smoothingPaint.setAntiAlias(true);
smoothingPaint.setFilterBitmap(true);
smoothingPaint.setDither(true);
canvas.drawBitmap(holeImageBMP, 0, 0, smoothingPaint);
Yet, as you can obviously see above, the image quality drastically decreases. I've seen plenty of images being rendered beautifully and I'm honestly just not sure what's going on so any advice would be great!
Other notes: I'm using a SurfaceView method to handle the drawing, similar in nature to the LunarLander example given in the SDK.
Thanks again!
If you aren't restricted to much less colors than the original picture has (Does Android have 256 color modes?), I'd suggest to disable dithering, if you zoom into your picture, it does have a visible effect that perhaps destroys a smooth look.
I think in your case, dithering infers with anti-aliasing by destroying the additional colors that anti-aliasing needs for a smooth look. A quick color count on your pictures (left one about 850, right one about 140) confirms this.
That is probably related to converting images from one format to another. Also, android screens vary from device to device. Try to use another device and it might look better... Almost for sure it will have a different tone.
Try to read this great article on this problem (and banding and dithering) and consider adapting the image you created for it to work better in android devices: http://www.curious-creature.org/2010/12/08/bitmap-quality-banding-and-dithering/
I have to scale an image with Java JAI. At the time now, I use the following code:
private static RenderedOp scale(RenderedOp image, float scale) {
ParameterBlock scaleParams = new ParameterBlock();
scaleParams.addSource(image);
scaleParams.add(scale).add(scale).add(0.0f).add(0.0f);
scaleParams.add(Interpolation.getInstance(Interpolation.INTERP_BICUBIC_2));
// Quality related hints when scaling the image
RenderingHints scalingHints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
scalingHints.put(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
scalingHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
scalingHints.put(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
scalingHints.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
scalingHints.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
scalingHints.put(JAI.KEY_BORDER_EXTENDER, BorderExtender.createInstance(BorderExtender.BORDER_COPY));
return JAI.create("scale", scaleParams, scalingHints);
}
Unfortunately, this leads to very bad results, especially because I often have to scale images with a scale factor less than 0.5...
Any advice?
I am guessing you are trying to scale a larger image down to a thumbnail size or some equally large difference from original to scaled image?
If-so, this topic was actually address by Chris Campbell from the Java2D back in 2007 (I am not expecting you knew this, just pointing out that it's a common question) because the new Java2D scaling approaches (RenderingHints.VALUE_INTERPOLATION_*) did not provide an equivalent to the then-deprecated Image.getScaledInstance(SCALE_AREA_AVERAGING or SCALE_SMOOTH) approach.
As it turns out, the SCALE_AREA_AVERAGING or SCALE_SMOOTH approaches in the old Java 1.1 Image.getScaledInstance approach was a fairly expensive, multi-step operation that was doing a lot of work in the background to generate that nice-looking image.
Chris pointed out that the new and "correct" way, using Java2D, to get this same result is an incremental process of scaling the image in-half over and over until the desired image size is reached, preferably using a higher-quality scale like RenderHints.VALUE_INTERPOLATION_BICUBIC or BILINEAR.
The result comes out almost identical to the original Image.getScaledInstance approach that folks want.
I actually went hunting for this answer a few months ago while writing an image-hosting service and was surprised at how complicated the simple question of "How do I make a nice looking thumbnail in Java?" became.
I eventually create a small Java library (Apache 2, open sourced) that implements 3 different approaches to image scaling in Java using "best practices" including the incremental approach that Chris suggested.
The library is called imgscalr. You can download and use it as simple as:
BufferedImage thumbnail = Scalr.resize(srcImage, 150);
There are more options to set and use (e.g. the Quality or Speed of the scaling) but out of the box there are intelligent defaults for everything to make a nice looking scaled image for you so you don't have to worry about more if you don't want to. The library also makes a strong effort to dispose of and avoid any Object allocation that isn't absolutely necessary and dispose of BufferedImage instances immediately if not needed -- it is intended to be code as part of a long-running server app so this was critical.
I've made a few releases of the library already, and if you'd rather just rip out the "good stuff" and do something with it yourself, go for it. It is all on GitHub and none of it is top secret, just an attempt to make people's lives easier.
Hope that helps.
I've obtained good results with Thumbnailator. I don't know what JAI.KEY_BORDER_EXTENDER is supposed to do, but I guess the rest of the functionality (antialiasing, dithering, etc) is supported.
I used it to generate grayscale thumbnails of quite big black and white images
If you are lucky and you have only Black & White images, then you can use very fast and good quality operation: SubsampleBinaryToGray
I have an Eclipse RCP application that displays a lot (10k+) of small images next to each other, like a film strip. For each image, I am using a SWT Image object. This uses an excessive amount of memory and resources. I am looking for a more efficient way. I thought of taking all of these images and concatenating them by creating an ImageData object of the proper total, concatenated width (with a constant height) and using setPixel() for the rest of the pixels. However, the Palette used in the ImageData constructor I can't figure out.
I also searched for SWT tiling or mosaic functionality to create one image from a group of images, but found nothing.
Any ideas how I can display thousands of small images next to each other efficiently? Please note that once the images are displayed, they are not manipulated, so this is a one-time cost.
You can draw directly on the GC (graphics context) of a new (big) image. Having one big Image should result in much less resource usage than thousands of smaller images (each image in SWT keeps some OS graphics object handle)
What you can try is something like this:
final List<Image> images;
final Image bigImage = new Image(Display.getCurrent(), combinedWidth, height);
final GC gc = new GC(bigImage);
//loop thru all the images while increasing x as necessary:
int x = 0;
int y = 0;
for (Image curImage : images) {
gc.drawImage(curImage, x, y);
x += curImage.getBounds().width;
}
//very important to dispose GC!!!
gc.dispose();
//now you can use bigImage
Presumably not every image is visible on screen at any one time? Perhaps a better solution would be to only load the images when they become (or are about to become) visible, disposing of them when they have been scrolled off the screen. Obviously you'd want to keep a few in memory on either side of the current viewport in order to make a smooth transition for the user.
I previously worked with a Java application to create photomosaics, and found it very difficult to achieve adequate performance and memory usage using the java imaging (JAI) libraries and SWT. Although we weren't using nearly as many images as you mention, one route was to rely on a utilities outside of java. In particular, you could use ImageMagick command-line utilities to stitch together your mosaic, and the load the completed memory from disk. If you want to get fancy, there is also a C++ API for ImageMagick, which is very efficient in memory.