Masking image that contains alpha makes the inner mask black - opengl

I'm trying to mask a background image that is smaller than the mask. and the space between the background and mask appears black.
This is the code I'm using:
batch.end();
batch.begin();
Gdx.gl20.glColorMask(false, false, false, true);
batch.setBlendFunction(GL20.GL_ONE, GL20.GL_ZERO);
batch.draw(mask, getX(), getY());
batch.flush();
Gdx.gl20.glColorMask(true, true, true, true);
batch.setBlendFunction(GL20.GL_DST_ALPHA, GL20.GL_ONE_MINUS_DST_ALPHA);
batch.draw(texture, getX(), getY());
batch.flush();
batch.setBlendFunction(GL20.GL_SRC_ALPHA,GL20.GL_ONE_MINUS_SRC_ALPHA);
batch.end();
batch.begin();
I tried all kind function combinations without any success. probably i'm missing something.
Update
Attaching chart that I build of all possible (relevant) results of src and dst blending function. Fortunately none of the below is working, and as I guessed there is something more need to be done in order to achieve the result.
Gdx.gl20.glColorMask(true, true, true, true);
batch.setBlendFunction(src_func, dst_func);
batch.draw(texture, getX(), getY());

Solved it using FrameBuffer.
batch.end();
spriteBatch.begin();
buffer.begin();
Gdx.gl20.glColorMask(false, false, false, true);
spriteBatch.setBlendFunction(GL20.GL_ONE, GL20.GL_ZERO);
spriteBatch.draw(mask, 0,0);
Gdx.gl20.glColorMask(true, true, true, true);
spriteBatch.setBlendFunction(GL20.GL_DST_ALPHA, GL20.GL_ZERO);
spriteBatch.draw(texture, 0,0);
spriteBatch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
buffer.end();
spriteBatch.end();
batch.begin();
batch.draw(buffer.getColorBufferTexture(), getX(), getY());

Just taking a look at your images, it looks like:
The alpha of the mask is in complete control of the output alpha
You want the alpha of the background image to also be taken into account
In other words, you only want alpha where both images have alpha.
I haven't yet been able to look into more of the blending functions and how they work, and may update with further details on how to achieve your goals as I figure it out, but maybe knowing what you are trying to accomplish will help you figure it out before I get to it.
How to do blending in LibGDX - this question seems interesting, combining the source and destination images in a grid to show the effects.

Related

Remove shadows with background subtraction for stationary objects detection

I've to detect a stationary object in a predefined area using Opencv V4.4.0. I'm working with two background subtractor that store two different background mask, one that store the stationary initial background mask, and one that detect the moving objects as updated mask; I've implemented them using MOG2 background subtractor, but the shadows removal system doesn't seem to works properly.
Instatiation of the two background subtractor MOG2:
Ptr<BackgroundSubtractorMOG2> bgSubtractor;
Ptr<BackgroundSubtractorMOG2> bgSubtractorMotion;
bgSubtractor = createBackgroundSubtractorMOG2(500, 16.0);
bgSubtractor->setDetectShadows(false);
bgSubtractor->setShadowValue(0);
//bgSubtractor->setShadowThreshold(50);
bgSubtractor->setVarThresholdGen(15);
bgSubtractor->setNMixtures(5);
bgSubtractorMotion = createBackgroundSubtractorMOG2(500, 16.0);
bgSubtractorMotion->setDetectShadows(false);
bgSubtractorMotion->setShadowValue(0);
//bgSubtractorMotion->setShadowThreshold(50);
bgSubtractorMotion->setVarThresholdGen(5);
bgSubtractorMotion->setNMixtures(5);
And I call the background removal as below:
// stationary initial background mask
bgSubtractor->apply(sourceFrame, backMaskFrame, 0.0);
blur(backMaskFrame, backMaskFrame, cv::Size(15, 15), cv::Point(-1, -1));
threshold(backMaskFrame, backMaskFrame, 254, 255, THRESH_BINARY);
// updated background mask
bgSubtractorMotion->apply(sourceFrame, backgroundSubtractionUpdatedFrame);
blur(backgroundSubtractionUpdatedFrame, backgroundSubtractionUpdatedFrame, cv::Size(15, 15), cv::Point(-1, -1));
threshold(backgroundSubtractionUpdatedFrame, backgroundSubtractionUpdatedFrame, 254, 255, THRESH_BINARY);
Now, I've to find the stationary objects in the area using the mask of moving object but the system recognize also shadows as stationary object, and this kind of problem doesn't make the system works correctly in daytime with a sunnyday and shadows well defined. I've tried to set the background detector property DetectShadows to false, but this seem be useless. I've tried also to threshold the resulting mask from the stationary background and the updated background, without any results.
There is a possible working solution to this problem?
Thanks in advance.

GLUQuadric Disk drawn but fill color is not solid

being a complete OpenGL newbie, I have a problem I do not understand how to solve. I am using JOGL, and trying to draw a disk, filled with a solid color and a different border color. My problem is obvious in the following image:
What I cannot understand is why I can still see the lines produced by GLU. The code that draws this is the following:
glColor3ub(r, g, b); // purple
gluDisk(quadric, 0, 50, 32, 2);
glColor3ub(r, g, b); // dark gray
gluDisk(quadric, 49, 50, 32, 2);
I suspect I have done something wrong with blending/anti-aliasing. When I disable anti-aliasing, the shape is drawn with solid color; however I need AA. I have set up AA and blending as shown below:
glEnable(GL2.GL_BLEND);
glBlendFunc(GL2.GL_SRC_ALPHA, GL2.GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL2.GL_LINE_SMOOTH);
glHint(GL2.GL_LINE_SMOOTH_HINT, GL2.GL_NICEST);
glEnable(GL2.GL_POLYGON_SMOOTH);
glHint(GL2.GL_POLYGON_SMOOTH_HINT, GL2.GL_NICEST);
Finally, my GLCanvas is created with the following GLCapabilities:
caps.setAlphaBits(16);
caps.setDoubleBuffered(true);
caps.setHardwareAccelerated(true);
Other than that, the Quadric rendering properties are the default. Does anybody understand what have I done wrong? I apologize for any information that might be missing! Thanks for reading!
Ilias
The culprit is GL_POLYGON_SMOOTH. Smoothing never worked painfree and artifacs like those you see are a result from that. A far better antialiasing method is multisampling. There's a tutorial at http://www.opengl.org/wiki/Multisampling

SDL Transparent Overlay

I would like to create a fake "explosion" effect in SDL. For this, I would like the screen to go from what it is currently, and fade to white.
Originally, I thought about using SDL_FillRect like so (where explosionTick is the current alpha value):
SDL_FillRect(screen , NULL , SDL_MapRGBA(screen->format , 255, 255 , 255, explosionTick ));
But instead of a reverse fading rectangle, it shows up completely white with no alpha. The other method I tried involved using a fullscreen bitmap filled with a transparent white (with an alpha value of 1), and blit it once for each explosionTick like so:
for(int a=0; a<explosionTick; a++){
SDL_BlitSurface(boom, NULL, screen, NULL);
}
But, this ended up being to slow to run in real time.
Is there any easy way to achieve this effect without losing performance? Thank you for your time.
Well, you need blending and AFAIK the only way SDL does it is with SDL_Blitsurface. So you just need to optimize that blit. I suggest benchmarking those:
try to use SDL_SetAlpha to use per-surface alpha instead of per-pixel alpha. In theory, it's less work for SDL, so you may hope some speed gain. But I never compared it and had some problem with this in the past.
you don't really need a fullscreen bitmap, just repeat a thick row. It should be less memory intensive and maybe there is a cache gain. Also you can probably fake some smoothness by doing half the lines at each pass (less pixels to blit and should still look like a global screen effect).
for optimal performance, verify that your bitmap is at the display format. Check SDL_DisplayFormatAlpha or possibly SDL_DisplayFormat if you use per-surface alpha

transparent colour being shown some of the time

I am using a LPDIRECT3DTEXTURE9 to hold my image.
This is the function used to display my picture.
int drawcharacter(SPRITE& person, LPDIRECT3DTEXTURE9& image)
{
position.x = (float)person.x;
position.y = (float)person.y;
sprite_handler->Draw(
image,
&srcRect,
NULL,
&position,
D3DCOLOR_XRGB(255,255,255));
return 0;
}
According to the book I have the RGB colour shown as the last parameter will not be displayed on screen, this is how you create transparency.
This works for the most part but leaves a pink line around my image and the edge of the picture. After trial and error I have found that if I go back into photoshop I can eliminate the pink box by drawing over it with the pink colour. This can be see with the ships on the left.
I am starting to think that photoshop is blending the edges of the image so that background is not all the same shade of pink though I have no proof.
Can anyone help fix this by programming or is the error in the image?
If anyone is good at photoshop can they tell me how to fix the image, I use png mostly but am willing to change if necessary.
edit: texture creation code as requested
character_image = LoadTexture("character.bmp", D3DCOLOR_XRGB(255,0,255));
if (character_image == NULL)
return 0;
You are loading a BMP image, which does not support transparency natively - the last parameter D3DCOLOR_XRGB(255,0,255) is being used to add transparency to an image which doesn't have any. The problem is that the color must match exactly, if it is off even by only one it will not be converted to transparent and you will see the near-magenta showing through.
Save your images as 24-bit PNG with transparency, and if you load them correctly there will be no problems. Also don't add the magenta background before you save them.
As you already use PNG, you can just store the alpha value there directly from Photoshop. PNG supports transparency out of the box, and it can give better appearance than what you get with transparent colour.
It's described in http://www.toymaker.info/Games/html/textures.html (for example).
Photoshop is anti-aliasing the edge of the image. If it determines that 30% of a pixel is inside the image and 70% is outside, it sets the alpha value for that pixel to 70%. This gives a much smoother result than using a pixel-based transparency mask. You seem to be throwing these alpha values away, is that right? The pink presumably comes from the way that Photoshop displays partially transparent pixels.

Fuzzy Top Edge with GDIPlus Resize

I'm using the following code to resize a bitmap using GDI+ in C. I'm getting gray values for the top edge even for images where that area should be white. The problem disappears when the interpolation is nearest neighbor. However, I tried bicubic interpolation with ImageMagick and it seems fine. Any limitations problems I should know of? Is my method of scaling wrong somehow? Thanks!
(inputs:
destSize : destination Gdiplus::Size
m_pBitmap : source bitmap)
Rect destRect(Point(0,0), destSize);
Bitmap *pBitmap24BPP = new Bitmap(destSize.Width, destSize.Height, PixelFormat24bppRGB);
pBitmap24BPP->SetResolution(m_pBitmap->GetHorizontalResolution(), m_pBitmap->GetVerticalResolution());
Graphics *pGraphics = Graphics::FromImage(pBitmap24BPP);
pGraphics->SetInterpolationMode(InterpolationModeHighQualityBilinear);
pGraphics->DrawImage(m_pBitmap, destRect, 0, 0, m_pBitmap->GetWidth(), m_pBitmap->GetHeight() , UnitPixel, NULL);
//cleanup
i've been seeing similar things. i've not had time to research it, but i have a feeling it is because the GDI+ image resizer is mistakenly using pixels values "off the top edge", which would be all zero - making it black.
Proper image resizing should recognize that you've reached the edge of the image, and handle it appropriately.