Added noise reduction

This commit is contained in:
Eduard Urbach 2018-04-11 20:23:16 +02:00
parent 5d4c0fdce2
commit 47af959f24

View File

@ -78,10 +78,7 @@ func (area *Area) AverageColor() color.Color {
} }
const ( const (
tolerance = uint32(3000) tolerance = uint32(3000)
hueTolerance = 0.1
lightnessTolerance = 0.1
saturationTolerance = 0.1
) )
func diffAbs(a uint32, b uint32) uint32 { func diffAbs(a uint32, b uint32) uint32 {
@ -97,7 +94,8 @@ func ImproveQuality(img image.Image) *image.NRGBA {
width := img.Bounds().Dx() width := img.Bounds().Dx()
height := img.Bounds().Dy() height := img.Bounds().Dy()
clone := image.NewNRGBA(image.Rect(0, 0, width, height)) clone := image.NewNRGBA(image.Rect(0, 0, width, height))
hueAreas := []Area{} areas := []Area{}
areaIndexMap := make([]int, width*height)
for x := 0; x < width; x++ { for x := 0; x < width; x++ {
for y := 0; y < height; y++ { for y := 0; y < height; y++ {
@ -106,8 +104,8 @@ func ImproveQuality(img image.Image) *image.NRGBA {
areaIndex := -1 areaIndex := -1
// Find similar area // Find similar area
for i := 0; i < len(hueAreas); i++ { for i := 0; i < len(areas); i++ {
area := hueAreas[i] area := areas[i]
avgR, avgG, avgB, _ := area.AverageColor().RGBA() avgR, avgG, avgB, _ := area.AverageColor().RGBA()
// Is the color similar? // Is the color similar?
@ -119,18 +117,108 @@ func ImproveQuality(img image.Image) *image.NRGBA {
// Insert new area // Insert new area
if areaIndex == -1 { if areaIndex == -1 {
areaIndex = len(hueAreas) areaIndex = len(areas)
hueAreas = append(hueAreas, Area{}) areas = append(areas, Area{})
} }
hueAreas[areaIndex].Add(x, y, r, g, b, a) areaIndexMap[y*width+x] = areaIndex
areas[areaIndex].Add(x, y, r, g, b, a)
} }
} }
fmt.Println(len(hueAreas), "areas") fmt.Println(len(areas), "areas")
// Reduce noise
noiseCount := 0
for r := 0; r < 30; r++ {
for areaIndex, area := range areas {
removals := []int{}
for i := 0; i < len(area.Pixels); i++ {
// If pixel is surrounded by 4 different areas, remove it
pixel := area.Pixels[i]
x := pixel.X
y := pixel.Y
left := areaIndex
right := areaIndex
top := areaIndex
bottom := areaIndex
if x > 0 {
left = areaIndexMap[y*width+(x-1)]
}
if x < width-1 {
right = areaIndexMap[y*width+(x+1)]
}
if y > 0 {
top = areaIndexMap[(y-1)*width+x]
}
if y < height-1 {
bottom = areaIndexMap[(y+1)*width+x]
}
differentNeighbors := 0
if left != areaIndex {
differentNeighbors++
}
if right != areaIndex {
differentNeighbors++
}
if top != areaIndex {
differentNeighbors++
}
if bottom != areaIndex {
differentNeighbors++
}
// Determine surrounding area
areaIndexScore := map[int]int{}
areaIndexScore[left]++
areaIndexScore[right]++
areaIndexScore[top]++
areaIndexScore[bottom]++
newAreaIndex := -1
bestScore := 0
for checkIndex, score := range areaIndexScore {
if score > bestScore {
bestScore = score
newAreaIndex = checkIndex
}
}
if differentNeighbors == 4 && bestScore >= 3 {
noiseCount++
removals = append(removals, i)
// Add to surrounding area
r, g, b, a := img.At(x, y).RGBA()
areas[newAreaIndex].Add(x, y, r, g, b, a)
}
}
offset := 0
for _, removal := range removals {
area.Pixels = append(area.Pixels[:removal-offset], area.Pixels[removal-offset+1:]...)
offset++
}
}
}
fmt.Println(noiseCount, "noise pixels")
// Build image from areas // Build image from areas
for _, area := range hueAreas { for _, area := range areas {
avgColor := area.AverageColor() avgColor := area.AverageColor()
for _, pixel := range area.Pixels { for _, pixel := range area.Pixels {