Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Usage

Reply
 
Thread Tools Search this Thread Display Modes
Old 18th December 2012, 05:37   #1  |  Link
vampiredom
Registered User
 
Join Date: Aug 2008
Posts: 233
Alternative to the old Unpremultiply() plugin?

Hi all –

I need to unpremultiply some matted RGB32 clips. I am currently using the Unpremultiply() function (ca. 2008) but the results are not always good. It tends to add dark or bright speckles, particularly in near-transparent areas.

Does anyone know of a good alternative to this or perhaps some updated/re-tooled version?

I have tried using a series of Overlay operations with different modes ... but no luck. Perhaps there is some way with MaskTools or something similar?

Thx.

Last edited by vampiredom; 18th December 2012 at 06:50.
vampiredom is offline   Reply With Quote
Old 18th December 2012, 07:44   #2  |  Link
IanB
Avisynth Developer
 
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,167
Assuming this source code unpremultiply.cpp
Code:
                                // Formula is: Cu = Cm / a
    // Adding alpha/2 rounds instead of truncates the result of integer division
    // This will cause horrible things to happen to your image if a color value
    // is ever greater than the alpha value.
    // This can happen if your source program used some kind of specular highlighting
    *dstbpix = (srcbpix * 255 + srcapix / 2) / srcapix;
    *dstgpix = (srcgpix * 255 + srcapix / 2) / srcapix;
    *dstrpix = (srcrpix * 255 + srcapix / 2) / srcapix;
A rookie mistake in not clamping the intermediate results between 0 and 255.

Apply this patch or similar
Code:
inline uint8_t uint8clamp(int x) {
    if (x < 0) return 0;
    if (x > 255) return 255;
    return x;
}
....
    *dstbpix = uint8clamp((srcbpix * 255 + srcapix / 2) / srcapix);
    *dstgpix = uint8clamp((srcgpix * 255 + srcapix / 2) / srcapix);
    *dstrpix = uint8clamp((srcrpix * 255 + srcapix / 2) / srcapix);
IanB is offline   Reply With Quote
Old 18th December 2012, 08:25   #3  |  Link
vampiredom
Registered User
 
Join Date: Aug 2008
Posts: 233
Nice find! Thank you. Any chance you would consider compiling this patched code into a new version? That would be fabulous.
vampiredom is offline   Reply With Quote
Old 27th December 2012, 09:10   #4  |  Link
IanB
Avisynth Developer
 
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,167
Try the attached version.

Also changed to uses a fast 65K lookup table instead of the slow in place idiv's.

:Edit: See below for new version

Last edited by IanB; 31st December 2012 at 23:55.
IanB is offline   Reply With Quote
Old 30th December 2012, 04:32   #5  |  Link
vampiredom
Registered User
 
Join Date: Aug 2008
Posts: 233
Thanks so much! I will try it out and get back to you.
vampiredom is offline   Reply With Quote
Old 31st December 2012, 21:38   #6  |  Link
vampiredom
Registered User
 
Join Date: Aug 2008
Posts: 233
Hi --

There is something strange going on: It seems that areas that should be fully opaque turn to black.

This can be demonstrated with a simple test:

Code:
# This works properly, showing a white rectangle with a gray rectangle

a = BlankClip(width=1280, height=720, length=1, color=$808080, pixel_type="RGB32").ResetMask()
b = BlankClip(width=640, height=480, length=1, color=$FFFFFF,  pixel_type="RGB32").ResetMask()

Layer(a, b, x=320, y=120)
Code:
# When Unpremultiply() is applied, the inner rectangle turns black

a = BlankClip(width=1280, height=720, length=1, color=$808080, pixel_type="RGB32").ResetMask()
b = BlankClip(width=640, height=480, length=1, color=$FFFFFF,  pixel_type="RGB32").ResetMask().Unpremultiply()

Layer(a, b, x=320, y=120)
Can you please check this out? Thanks again.
vampiredom is offline   Reply With Quote
Old 31st December 2012, 23:07   #7  |  Link
IanB
Avisynth Developer
 
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,167
Opps, The bottom row and right column of the lookup table are not being initialised.
Code:
		for (int i=0; i< 255; i++) {
			lookup[i<<8] = i;
			for (int j=1; j<255; j++)
				lookup[(i<<8)+j] = uint8clamp((i * 255 + j / 2) / j);
		}
See attached :-
Attached Files
File Type: zip Unpremultiply.zip (33.2 KB, 395 views)

Last edited by IanB; 31st December 2012 at 23:54.
IanB is offline   Reply With Quote
Old 2nd January 2013, 19:51   #8  |  Link
vampiredom
Registered User
 
Join Date: Aug 2008
Posts: 233
Ah, much better! I have not tested it thoroughly but it seems to work well on some tests I have tried.

However, it seems to only work correctly when the matte color is black. I wish there were a way (similar to Adobe After Effects, for example) where you could choose the matte color to remove. Photoshop has a similar-but-simplified approach with "Matting > Remove Black Matte" and "Matting > Remove White Matte".

Unpremultiply() wreaks havoc on a white-matted clip.
vampiredom is offline   Reply With Quote
Old 2nd January 2013, 23:00   #9  |  Link
IanB
Avisynth Developer
 
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,167
From our PM exchange
Quote:
Originally Posted by ianb
Quote:
Originally Posted by vampiredom
If possible, I'd also like to be able to specify a matte color to override the function's automatic assumption.
The source I looked at didn't have any matte colour processing. It simply unmultiplied the source pixels by the alpha channel (without range checking).
Here is the original code :-
Code:
    // Formula is: Cu = Cm / a
    // Adding alpha/2 rounds instead of truncates the result of integer division
    // This will cause horrible things to happen to your image if a color value
    // is ever greater than the alpha value.
    // This can happen if your source program used some kind of specular highlighting
    *dstbpix = (srcbpix * 255 + srcapix / 2) / srcapix;
    *dstgpix = (srcgpix * 255 + srcapix / 2) / srcapix;
    *dstrpix = (srcrpix * 255 + srcapix / 2) / srcapix;
If you want to propose changes to allow selection of the matte colour, I am happy to consider compiling your modified version.


As for unpremultiplying based on a [255,255,255] white matte you could try this :-
Code:
...source
Invert("RGB") # flip rgb channels
Unpremultiply() # Orgb = 255 - ( (255 - Irgb) * 255 / Ia )
Invert("RGB") # unflip rgb channels
..
A more general approach could be to split out the argb channels to yv12 clips and use mt_lutxy to do arbitrary 2 value function processing on the pixels. E.g.
Code:
...
Ya=ShowAlpha("YV12") # Copy alpha to Y plane
Ya3=Interleave(Ya, Ya, Ya)
Interleave( ShowRed("YV12"), ShowGreen("YV12"), ShowBlue("YV12") )  # Copy rgb's to Y planes
exprstr=mt_polish( "255 - ( ( ( 255 - X ) * 255 + Y / 2 ) / Y )" ) # "255 255 x - 255 * y 2 / + y / -"
Mt_LutXY(Ya3, yexpr=exprstr, y=3, u=1, v=1) # do Y, ignore U and V
MergeARGB( Ya, SelectEvery(3,0), SelectEvery(3,1), SelectEvery(3,2) ) # Reassemble Y's to ARGB

Last edited by IanB; 28th June 2013 at 22:58. Reason: Fix Ya3 bug as per Gavino
IanB is offline   Reply With Quote
Old 28th June 2013, 17:06   #10  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
Quote:
Originally Posted by IanB View Post
Code:
...
Ya=ShowAlpha("YV12") # Copy alpha to Y plane
Interleave( ShowRed("YV12"), ShowGreen("YV12"), ShowBlue("YV12") )  # Copy rgb's to Y planes
exprstr=mt_polish( "255 - ( ( ( 255 - X ) * 255 + Y / 2 ) / Y )" ) # "255 255 x - 255 * y 2 / + y / -"
Mt_LutXY(Ya, yexpr=exprstr, y=3, u=1, v=1) # do Y, ignore U and V
MergeARGB( Ya, SelectEvery(3,0), SelectEvery(3,1), SelectEvery(3,2) ) # Reassemble Y's to ARGB
A neat way of using MaskTools on RGB input.
But don't you need to replicate the alpha channel three times as well, otherwise the wrong frames will be paired up in the mt_lutxy?
I think the Ya in the mt_lutxy call should be Interleave(Ya, Ya, Ya).
(unless you are assuming a single frame clip or a static image.)
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 28th June 2013, 22:59   #11  |  Link
IanB
Avisynth Developer
 
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,167
Yes Oops
IanB is offline   Reply With Quote
Reply

Tags
alpha, matte, premultiplied, rgb32, unpremultiply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 11:24.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.