Photoshop like brush with OpenCV - opencv

I am trying to add some blur brush stroke with OpenCV
If I use cv.add or cv.addweighted, I only got half of the red color (look pink),
but I want the red to cover the underlying picture, not blend.
If I use copyto or clone, I can't get the blur edge, so how should I do it ??

The background of your brush image is black. If you were in photoshop and set that brush layer's blend mode to screen the red gradient would show through and the black background would become transparent.
Here are a couple of relevant posts:
How does photoshop blend two images together?
Trying to translate formula for blending mode
Alternatively, if you're using OpenCV 3.0 you try using seamlessClone.

I got a trick to do it simply copy the area to a new mat, then draw a circle and blur it on the new mat, and use addWeighted to blend it to the image with whatever alpha I need.
Mat roi = myImage.submat(y-20, y+20, x-20, x+20);
Mat mix = roiB.clone();
Imgproc.circle(mix, new Point(20, 20), 12, color, -1);
Core.addWeighted(mix, alpha, roiB, beta, 0.0, mix);
Imgproc.GaussianBlur(mix, mix, new Size(21, 21), 0);
mix.copyTo(roiB);

Related

Simulate one color printing using Fabric.js

I would like to apply filters to a full color image using Fabric.js in order to simulate what it would look like if the image were to be printed using only one color of ink. Much like grayscale, but with an arbitrary base color instead of gray. My approach so far has been to convert the image to grayscale and then adjust the brightness and apply a tint or overlay using BlendColor. This solution tends to give images that are too dark or washed out. What's the most technically correct/accurate way to do this?
Here is what I have tried so far:
var grayscale = ThirdPartyLibrary.getFilter('grayscale'); // using the grayscale filter from another lib
var brightness = new fabric.Image.filters.Brightness({
brightness: 0.2
});
var tint = new fabric.Image.filters.BlendColor({
color: '#3b7998',
mode: 'tint',
alpha: 0.5
});
element.applyFilters([grayscale, brightness, tint]);
Any input is appreciated, even if just the basic approach and I can figure out how to implement the filters in Fabric.js.
If you are trying to get an effect like this:
You should be able to obtain it with using first the greyscale filter of fabricJS with the average mode, and then the blendColor with multiply mode.
Image luminance shouldn't change, but it won't work perfectly with all colors.
You need to pick up colors that have max saturation and lightness at 50%.
You have just the HUE as a free parameter.
You can generate them with the fabric color utils:
const hsl = `hsl(${Math.round(value * 360)}, 100%, 50%)`;
const [r,g,b] = fabric.Color.sourceFromHsl(hsl);

GPUImage GPUImageFalseColorFilter giving wrong color and coloring transparent areas

I have a green button with a white icon and title. I am trying to use the GPUImage library that I just learned about to change the green to blue, but keep the white as white. Here is my code:
UIImage *inputImage = [UIImage imageNamed:#"pause-button"];
GPUImageFalseColorFilter *colorSwapFilter = [[GPUImageFalseColorFilter alloc] init];
colorSwapFilter.firstColor = (GPUVector4){0.0f, 0.0f, 1.0f, 1.0f};
colorSwapFilter.secondColor = (GPUVector4){1.0f, 1.0f, 1.0f, 1.0f};
UIImage *filteredImage = [colorSwapFilter imageByFilteringImage:inputImage];
There are 2 problems:
The resulting image is a pale purple instead of blue. Almost as though the blue is being overlaid with a 50% opacity or something and the original green was set to white.
The button isn't a rectangle (more of an oval), and the transparent areas of the PNG (the corners) are now filled in with a semi-transparent blue (well, pale purple actually). Basically the button is now a rectangle with a darker oval in the middle.
Am I using this filter incorrectly? Do I have to do some pre-processing before using this filter?
The GPUImageFalseColorFilter is probably not what you want to use to alter the hue of something. It's a reimplementation of the filter by the same name in Core Image, which first converts an image to its luminance and then replaces white with one color and black with another. Instead of a grayscale, you get a variable mix between these colors. I also don't think it respects alpha channels at present.
You might want something more like a GPUImageHueFilter (again, not sure if it respects alpha) or a GPUImageLookupFilter. You might need to build a custom filter to locate a color within a certain threshold (look at the chroma keying ones for that) and to replace that with your given color. Hue changes might do the job, though.

Put border around partially transparent Image being drawn on CGContext

I have an image with a yellow vase in the foreground and transparent background:
I'm drawing it on a CGContext:
CGContextDrawImage(context, CGRectMake(0, 0, 100, 100), myImage.CGImage);
I can draw a shadow around it by using the following statement before CGContextDrawImage:
CGContextSetShadowWithColor(context, CGSizeMake(0,0), 5, [UIColor blueColor].CGColor);
But I want to put a stroke around the image, so that it'll looks like following:
If I did this:
CGContextSetRGBStrokeColor(shadowContext, 0.0f, 0.0f, 1.0f, 1.0f);
CGContextSetLineWidth(shadowContext, 5);
CGContextStrokeRect(shadowContext, CGRectMake(0, 0, 100, 100));
It (obviously) draws a rectangular border around the whole iamge like this:
Which is not what I need.
But what's the best way to draw the border as in the third image?
Please note that it's not possible to use UIImageView in this case, so using the properties of CALayer of UIImageView is not applicable.
One way to do this is to use the mathematical morphology operator of dilation to "grow" the alpha channel of the image outward, then use the resulting grayscale image as a mask to simulate a stroke. By filling the dilated mask, then drawing the main image on top, you get the effect of a stroke. I've created a demo showing this effect, available on Github here: https://github.com/warrenm/Morphology (all source is MIT licensed, should it prove useful to you).
And here's a screenshot of it in action:
Note that this is staggeringly slow (dilation requires iteration of a kernel over every pixel), so you should pick a stroke width and precompute the mask image for each of your source images in advance.
I would try either setting the stroke color and line width before your call to CGContextDrawImage, or tweaking the shadow (opacity, blur, etc) so that it looks like a stroke around the image. Let me know if this works!

Delphi TBitBtn white layer

How can I get rid of the white layer drawn under the bitmap images by Delphi/Windows when Glyph property of TBitBtn is used. I just want to draw the image, no shadow under it, no other layers that comes automatically. I am inserting round shaped 24 bit bitmap images.
Since you have a 24-bit bitmap, there is no alpha transparency, so Delphi uses the bottom left pixel of the image to determine the transparent color. All pixels with that color are treated as transparent. The part of the image with the shadow effect is not an exact match for the designated transparent color, so those pixels are painted normally, just like the rest of the image.
The shadow appears white because there was a white background in the graphic program when your designer applied the shadow effect.
Either edit the image to remove the shadow, or use a 32-bit image with alpha transparency. You'll be hard-pressed to apply alpha transparency after the fact. Fix the source image.

openCV: adding transparency to IplImage

I have a 3-channel IplImage. I would like to create a 4-channel image and set the alpha channel for it to a value less than 1.0 to make it semi-transparent.
First I set the alpha channel (the 4-th channel) to 0.5:
cvSet(Image_c4, cvScalar(0,0,0,0.5);
Here is the command that I used to copy the 3-channel image into a 4-channel image.
cvCvtColor(Image_c3, Image_c4, CV_RGB2RGBA);
The problem: Image_c3 is in color. Image_c4 becomes a gray scale copy of Image_c3 (and with no transparency).
Update:
It turned out that the code above is actually correct and works and is actually more concise than the suggested solutions in the answers below. I had an unrelated bug somewhere else.
Maybe there is another way but I add transparency like this:
// BGR split
cvSplit(im1_bgr, im1_b, im1_g, im1_r, NULL);
// Alpha channel creation (transparency)
IplImage *im1_a = cvCreateImage(cvGetSize(im1_bgr), 8, 1);
// Set the alpha value
cvSet(im1_a, cvScalar(128), NULL);
// Merge the 4 channel to an BGRA image
IplImage *im1_bgra = cvCreateImage(cvGetSize(im1_bgr), 8, 4);
cvMerge(im1_b, im1_g, im1_r, im1_a, im1_bgra);
//This code help to make a transparency image But it take src image as one //single color background see![Removing background and added black background color ][1]
Mat dst;//(src.rows,src.cols,CV_8UC4);
Mat tmp,alpha;
cvtColor(src,tmp,CV_BGR2GRAY);
threshold(tmp,alpha,0,255,THRESH_BINARY);
Mat rgb[3];
split(src,rgb);
Mat rgba[4]={rgb[0],rgb[1],rgb[2],alpha};
merge(rgba,4,dst);
imwrite("dst.png",dst);
//dst is transparency image see here![output image as transparency image][2]
[1]: http://i.stack.imgur.com/9THqs.png
[2]: http://i.stack.imgur.com/mpmgy.png

Resources