Log in

View Full Version : Cleaning random single pixel noise in a mask


some drywall
2nd May 2007, 12:36
First thing, hats off to everyone that has contributed to avisynth. Ive been using it for a few months now and it is great.

Im looking for some script help. Been working on encoding my collection of southpark episodes to wmv. The DVD quality isn't really that great. The luma plane can be cleaned up fairly easy, but ive been stumbling over cleaning the chroma planes for a while now. The script below is giving excellent results... I just have to run an instance of it with different thresholds for each dominant color. It creates a mask based on the pixel values within a certain range on each color plane. Then overlays the smooth color based on the mask. However im having trouble removing the noise from the mask. Mostly it is single pixels being outside the thresholds... so ill end up with luma value 0 pixels surround by luma value 255 pixels, and of course the other way around.

Im looking for some help on a way to inpand or expand those single pixels. Ive made some attempts with inpand, expand, inflate, and deflate. Deflate followed by binarize gets rid of some noise, but using enough inflates and deflates to kill the noise messes up the edges. For example if a white dot was surrounded by black on top, bottom, left, and right I want to set it to black also, but only if it is completely surrounded by black. And the same for black pixels surrounded by white. This would smooth the masks out alot without having to increase my thresholds, introduce more noise, or mess up the edges. I would greatly appreciate any help.

Thanks


LoadPlugin("D:\DGIndex\DGDecode.dll")
video = MPEG2Source("D:\800\801.d2v")
audio = WAVSource("D:\800\801 T01 2_0ch 192Kbps 48KHz.wav")
AudioDub(audio,video)
Trim(1010,39549)
AssumeTFF()
interp = separatefields().selecteven().EEDI2(field=1)
deinted = tdeint(order=1,field=1,edeint=interp)
TFM(mode=1,order=1,clip2=deinted)
orig = Decimate()
yorig = GreyScale(orig)
uorig = UToY(orig).EEDI2().TurnLeft().EEDI2().TurnRight()
vorig = VToY(orig).EEDI2().TurnLeft().EEDI2().TurnRight()

#Dark Grey - Pavement Masking
clrclp4 = BlankClip(orig, pixel_type="YV12", color_yuv=$3E7F7F)
yclp4 = mt_lut(yorig, yexpr="x 55 >= x 70 <= & 50 0 ?")
uclp4 = mt_lut(uorig, yexpr="x 122 >= x 132 <= & 50 0 ?")
vclp4 = mt_lut(vorig, yexpr="x 122 >= x 132 <= & 50 0 ?")
yumsk = mt_lutxy(yclp4, uclp4, yexpr="x y +")
msk4 = mt_lutxy(yumsk, vclp4, yexpr="x y +")\
.mt_binarize(threshold=140)\
.mt_deflate().mt_deflate()\
.mt_binarize(threshold=80)
mt_merge(orig, clrclp4, msk4, luma=true)

wonkey_monkey
2nd May 2007, 13:00
Thinking off the top of my head again...

What if you did a 3x3 box blur, then took a threshold so only those pixels with 8 (or 9 including self) white pixels surrounding got through? I think you'd set the threshold at around 224 out of 255, or 88%. Then, lighten or OR with the original mask, and that should fill in the white pixels. Invert the image, repeat, and re-invert and that should fill in the black pixels too.

David

some drywall
2nd May 2007, 16:15
Thanks for the reply david. While reading your comment about the threshold it stuck me that I wasn't putting enough thought into the binarize threshold after the deflate. It was right there in front of me.

With one instance of deflate... then a binarize with a threshold of 60 kills the white pixels. Then invert, repeat, and invert removes the black pixels like you said. The original 80 I was using was just some random number I picked.

.mt_deflate().mt_binarize(threshold=60).mt_invert()\
.mt_deflate().mt_binarize(threshold=60).mt_invert()
:smackhead: