# Color Ghosting

1. Hello guys, I have been trying everything on both this forum and others on all threads that I found related to this problem, but without success.
Here is my problem:

[Attachment 45692 - Click to enlarge]

Here is how the Chroma and Luma channel appear:
Frame 0 (Ghosting has yet to occur)

[Attachment 45693 - Click to enlarge]

Frame 1 (Ghosting first appears)

[Attachment 45694 - Click to enlarge]

Frame 2 (Ghosting still present, appears to be an exact duplicate of Frame 1)

[Attachment 45695 - Click to enlarge]

Frame 3 (Ghosting is gone)

[Attachment 45696 - Click to enlarge]

This is the pattern in which the ghosting appears through the video.
Please guys this has been driving me nuts.
2. Common problem caused by treating interlaced YV12 chroma as progressive. Could be in your source or the way you're handling it. What's your source? What are you doing with it? Upload a sample of your source, not re-encoded.
3. It's definitely the source, downloaded the clip from YT, All I want to do is actually remove the ghosting itself. Here is the clip completely untouched.
4. Yes, the problem is definitely in your source, and from the bad interlaced YV12 treatment I described earlier.

I was going to say there was no way to fix it. But I recently successfully removed blends from a video where every 4th frame was a 50:50 blend of that frame and the next. Essentially: blended = (frame[N] + frame[N+1]) / 2. Since that's a simple algebraic equation it should be possible to reverse it. If:

Code:
`blended = (frame[N] + frame[N+1]) / 2`
and we want to see frame(N), some simple algebraic manipulation gives:

Code:
```blended * 2 = frame[N] + frame[N+1]
blended * 2 - frame[N+1] = Frame[N]```
Your case is similar except only the chroma channels are blended. And it's not an easy pattern like every 4th frame. By using this technique I was able generate clean chroma (aside from some artifacts from compression) for most of the bad frames. For example (black borders cropped and half size):

On the left is the original frame, on the right the unblended frame. Unfortunately, applying that same manipulation to frames without blending messes them up:

So some way needs to be developed to figure out which frames have blending and only replace those frames.

I did this with an AviSynth script (I don't think you'll find any way to do this without AviSynth):

Code:
```# get the source video

# unblend all frames
unblended = Overlay(last, last.Trim(1, 0).ColorYUV(gain_y=-128, cont_u=-128, cont_v=-128), mode="subtract").ColorYUV(gain_y=256, cont_u=256, cont_v=256)

# merge the original luma with the unblended chroma
MergeChroma(last, unblended)```
So there's some hope of a fix. The technique has to be modified to replace only the frames with blended chroma. I'll have to think about that some more...
5. Holy smokes, jagabo that is some amazing feat you already pulled off there, I really thought it was kind of a lost cause
I am decently familiar with Avisynth so that should not be a problem. Thank You so amuch for what you've done so far Looking forward for an update, but you've done so much already, I'll patiently wait as much as I have to!
6. This is better known as "chroma trails".
It's always caused by poor processing, usually homemade stuff.
7. Originally Posted by lordsmurf
This is better known as "chroma trails".
It's always caused by poor processing, usually homemade stuff.
That`s funny Amazon UK offers these episodes as well, and they seem to have the same source as the YouTube channels because they have the same issue. Obviously someone at Cartoon Network didn't know very well what they were doing. I also own the dvds and they don't have this issue, My theory is that they screwed up the deinterlacing. (I want to use the YT/Amazon clips because I confronted them with the DVDs, and they actually have more details and better quality).
8. If you own DVDs without this problem why are you working with youtube downloads? The youtube video is obviously upscaled from SD. You can probably do a better job of upscaling from the DVDs and avoid this blended chroma problem.

That said... I've come up with this for detecting whether the source or the "unblended" frame is the right one to keep:

Code:
```function ChromaOnlyEdges(clip v)
{
v.BilinearResize((v.width/16)*4, (v.height/16)*4).TNLMeans(ax=2, ay=2, h=3.0) # use small mod4 image, with string 2d noise reduction
luma = GreyScale().mt_edge(chroma="-128").mt_expand(chroma="-128").mt_expand(chroma="-128") # luma edges, expand
CU = Tweak(sat=2.0).UtoY().mt_edge(chroma="-128").PointResize(luma.width, luma.height) # U edges
CV = Tweak(sat=2.0).VtoY().mt_edge(chroma="-128").PointResize(luma.width, luma.height) # V edges
Overlay(last, luma, mode="subtract") # remove UV edges near Y edges
}

Trim(3843,3925)

Crop(240,0,-240,-0)
#BilinearResize(width/2, height/2)
src=last # remember the source so we can view it later

# created unblended frames assuming 50:50 blending.  This messes up frames without any blending
unblended = Overlay(last, last.Trim(1,0).ColorYUV(gain_y=-128,cont_u=-128,cont_v=-128), mode="subtract").ColorYUV(gain_y=256,cont_u=256,cont_v=256)
unblended = MergeChroma(last, unblended) # keep the original luma

# enable the following line if you want to see the chroma edges
#return(StackHorizontal(ChromaOnlyEdges(src), ChromaOnlyEdges(unblended)))

testclip = Subtract(ChromaOnlyEdges(src), ChromaOnlyEdges(unblended))
ConditionalFilter(testclip, src, unblended, "AverageLuma", "LessThan", "126.0")

#view source, unblended, final clips
StackHorizontal(src, unblended, last)
BilinearResize(width/3, height/3) # smaller so we can see it all.```
You can try changing the 126.0 threshold in ConditionalFilter() to bias the choice one way or the other.

This only works the parts of the cartoon where frames have 50:50 blends of the chroma. There are other parts of the video where there is blending to a lesser degree -- this doesn't fix those. The code will occasionally pick the wrong frame (especially if there is very little motion) so I would use it only on parts of the video that have this problem. For example frames 3843 to 3925. That's the section I used to test the algorithms. And even when it works, it's not always "perfect".
9. Originally Posted by jagabo
If you own DVDs without this problem why are you working with youtube downloads? The youtube video is obviously upscaled from SD. You can probably do a better job of upscaling from the DVDs and avoid this blended chroma problem.

That said... I've come up with this for detecting whether the source or the "unblended" frame is the right one to keep:

Code:
```function ChromaOnlyEdges(clip v)
{
v.BilinearResize((v.width/16)*4, (v.height/16)*4).TNLMeans(ax=2, ay=2, h=3.0) # use small mod4 image, with string 2d noise reduction
luma = GreyScale().mt_edge(chroma="-128").mt_expand(chroma="-128").mt_expand(chroma="-128") # luma edges, expand
CU = Tweak(sat=2.0).UtoY().mt_edge(chroma="-128").PointResize(luma.width, luma.height) # U edges
CV = Tweak(sat=2.0).VtoY().mt_edge(chroma="-128").PointResize(luma.width, luma.height) # V edges
Overlay(last, luma, mode="subtract") # remove UV edges near Y edges
}

Trim(3843,3925)

Crop(240,0,-240,-0)
#BilinearResize(width/2, height/2)
src=last # remember the source so we can view it later

# created unblended frames assuming 50:50 blending.  This messes up frames without any blending
unblended = Overlay(last, last.Trim(1,0).ColorYUV(gain_y=-128,cont_u=-128,cont_v=-128), mode="subtract").ColorYUV(gain_y=256,cont_u=256,cont_v=256)
unblended = MergeChroma(last, unblended) # keep the original luma

# enable the following line if you want to see the chroma edges
#return(StackHorizontal(ChromaOnlyEdges(src), ChromaOnlyEdges(unblended)))

testclip = Subtract(ChromaOnlyEdges(src), ChromaOnlyEdges(unblended))
ConditionalFilter(testclip, src, unblended, "AverageLuma", "LessThan", "126.0")

#view source, unblended, final clips
StackHorizontal(src, unblended, last)
BilinearResize(width/3, height/3) # smaller so we can see it all.```
You can try changing the 126.0 threshold in ConditionalFilter() to bias the choice one way or the other.

This only works the parts of the cartoon where frames have 50:50 blends of the chroma. There are other parts of the video where there is blending to a lesser degree -- this doesn't fix those. The code will occasionally pick the wrong frame (especially if there is very little motion) so I would use it only on parts of the video that have this problem. For example frames 3843 to 3925. That's the section I used to test the algorithms. And even when it works, it's not always "perfect".
Thank you so much!! I`ll try out the code as soon as I get home tomorrow. I want to use these sources instead of the dvds because even though they clearly are not raw 1080p somehow they do have more details and all the artifacts from the dvds are gone. My guess is that they used the 576i raw files and upscaled them to 1080p, but in order to do that they had to deinterlace and they obviously screwed that one up.
10. I changed the code to make it easier to use:

Code:
```function ChromaOnlyEdges(clip v)
{
v.BilinearResize((v.width/16)*4, (v.height/16)*4).TNLMeans(ax=2, ay=2, h=3.0) # use small mod4 image, with string 2d noise reduction
luma = GreyScale().mt_edge(chroma="-128").mt_expand(chroma="-128").mt_expand(chroma="-128") # luma edges, expand
CU = Tweak(sat=2.0).UtoY().mt_edge(chroma="-128").PointResize(luma.width, luma.height) # U edges
CV = Tweak(sat=2.0).VtoY().mt_edge(chroma="-128").PointResize(luma.width, luma.height) # V edges
Overlay(last, luma, mode="subtract") # remove UV edges near Y edges
}

function DeBlendChroma(clip v)
{
unblended = Overlay(v, v.Trim(1,0).ColorYUV(gain_y=-128,cont_u=-128,cont_v=-128), mode="subtract").ColorYUV(gain_y=256,cont_u=256,cont_v=256)
unblended = MergeChroma(v, unblended) # keep original luma

testclip = Subtract(ChromaOnlyEdges(v), ChromaOnlyEdges(unblended))
ConditionalFilter(testclip, v, unblended, "AverageLuma", "LessThan", "126.0")
}

Trim(3843,3925) # part of video with 50:50 blended chroma
Crop(240,0,-240,-0) # remove black borders
DeBlendChroma()```
So all you need to do is call DeBlendChroma().

Note that the trimmed section that's used here frame number 18 remains blended. This is because frame 19 is also blended -- so subtracting 19 from 18 gets you worse artifacts than in the original. You can deblend frame 18 by calling DeBlendChroma() a second time. In the first pass frame 19 is deblended, in the second frame 18 is deblended using the deblended frame 19.
11. Originally Posted by icebox616
I want to use these sources instead of the dvds because even though they clearly are not raw 1080p somehow they do have more details and all the artifacts from the dvds are gone. My guess is that they used the 576i raw files and upscaled them to 1080p, but in order to do that they had to deinterlace and they obviously screwed that one up.

What kind of artifacts does your DVD version have?

How bad is the DVD version chroma ? Maybe you can "frankenstein" mix & match the better parts from each ?
12. Here is the kind of difference and artifacts I am talking about between the DVDs and Amazon/YT.
I also thought about "muxing somehow the chroma/luma of the DVDs with the "HD" clips, but I wouldn't know where to start. There is also the problem that the sources have different framerates and the DVDs are interlaced
13. Those problems may be more easily fixed than chroma blending artifacts. I recommend you upload a non-reencoded sample of the DVD source. You can use a program like DgIndex (part of the DgMpgDec package for AviSynth) or Mpg2Cut2 to extract a short sample and upload it to this site.
14. Originally Posted by jagabo
Those problems may be more easily fixed than chroma blending artifacts. I recommend you upload a non-reencoded sample of the DVD source. You can use a program like DgIndex (part of the DgMpgDec package for AviSynth) or Mpg2Cut2 to extract a short sample and upload it to this site.
I know, in fact I was able to fix these issues in the DVD sources, but that does not recover the extra details the Youtube/Amazon sources offer. That's why I'm after a fix for the later ones.

Statistics