mirror of
https://github.com/Myzel394/simple-seam-carving-in-go.git
synced 2025-06-18 07:25:30 +02:00
feat: Add edge detection filter
This commit is contained in:
commit
3836eb5f83
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
assets
|
||||
image.png
|
||||
.idea
|
5
go.mod
Normal file
5
go.mod
Normal file
@ -0,0 +1,5 @@
|
||||
module myzel394.app/image-stuff
|
||||
|
||||
go 1.23.3
|
||||
|
||||
require gonum.org/v1/gonum v0.15.1 // indirect
|
2
go.sum
Normal file
2
go.sum
Normal file
@ -0,0 +1,2 @@
|
||||
gonum.org/v1/gonum v0.15.1 h1:FNy7N6OUZVUaWG9pTiD+jlhdQ3lMP+/LcTpJ6+a8sQ0=
|
||||
gonum.org/v1/gonum v0.15.1/go.mod h1:eZTZuRFrzu5pcyjN5wJhcIhnUdNijYxX1T2IcrOGY0o=
|
110
image_analyzer.go
Normal file
110
image_analyzer.go
Normal file
@ -0,0 +1,110 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"math"
|
||||
)
|
||||
|
||||
type ImageAnalyzer struct {
|
||||
image.Image
|
||||
}
|
||||
|
||||
// Calculate the energy using the dual-gradient energy function
|
||||
func getEnergy(
|
||||
firstPixel color.Color,
|
||||
secondPixel color.Color,
|
||||
) float64 {
|
||||
firstRed, firstGreen, firstBlue, _ := firstPixel.RGBA()
|
||||
firstRed, firstGreen, firstBlue = firstRed >> 8, firstGreen >> 8, firstBlue >> 8
|
||||
secondRed, secondGreen, secondBlue, _ := secondPixel.RGBA()
|
||||
secondRed, secondGreen, secondBlue = secondRed >> 8, secondGreen >> 8, secondBlue >> 8
|
||||
|
||||
return float64(
|
||||
math.Abs(float64(firstRed - secondRed)) +
|
||||
math.Abs(float64(firstGreen - secondGreen)) +
|
||||
math.Abs(float64(firstBlue - secondBlue)),
|
||||
)
|
||||
}
|
||||
|
||||
// Calculate a 0-255 grayscale value from a color using the NTSC formula
|
||||
func colorToGray(color color.Color) float64 {
|
||||
red, green, blue, _ := color.RGBA()
|
||||
red, green, blue = red >> 8, green >> 8, blue >> 8
|
||||
|
||||
return 0.299 * float64(red) +
|
||||
0.587 * float64(green) +
|
||||
0.114 * float64(blue)
|
||||
}
|
||||
|
||||
func sumSlice(slice []float64) float64 {
|
||||
var sum float64
|
||||
for _, value := range slice {
|
||||
sum += value
|
||||
}
|
||||
return sum
|
||||
}
|
||||
|
||||
func (image *ImageAnalyzer) CalculateEnergyAt(x int, y int) float64 {
|
||||
northPixel := image.At(
|
||||
x,
|
||||
max(0, y - 1),
|
||||
)
|
||||
northEastPixel := image.At(
|
||||
min(image.Bounds().Max.X, x + 1),
|
||||
max(0, y - 1),
|
||||
)
|
||||
eastPixel := image.At(
|
||||
min(image.Bounds().Max.X, x + 1),
|
||||
y,
|
||||
)
|
||||
southEastPixel := image.At(
|
||||
min(image.Bounds().Max.X, x + 1),
|
||||
min(image.Bounds().Max.Y, y + 1),
|
||||
)
|
||||
southPixel := image.At(
|
||||
x,
|
||||
min(image.Bounds().Max.Y, y + 1),
|
||||
)
|
||||
southWestPixel := image.At(
|
||||
max(0, x - 1),
|
||||
min(image.Bounds().Max.Y, y + 1),
|
||||
)
|
||||
westPixel := image.At(
|
||||
max(0, x - 1),
|
||||
y,
|
||||
)
|
||||
northWestPixel := image.At(
|
||||
max(0, x - 1),
|
||||
max(0, y - 1),
|
||||
)
|
||||
|
||||
thisPixel := image.At(
|
||||
x,
|
||||
y,
|
||||
)
|
||||
|
||||
_ = thisPixel
|
||||
_ = northPixel
|
||||
_ = northEastPixel
|
||||
_ = southPixel
|
||||
|
||||
horizontalMatrix := []float64{
|
||||
colorToGray(northWestPixel), 0, -colorToGray(northEastPixel),
|
||||
2 * colorToGray(westPixel), 0, -2 * colorToGray(eastPixel),
|
||||
colorToGray(southWestPixel), 0, -colorToGray(southEastPixel),
|
||||
}
|
||||
verticalMatrix := []float64{
|
||||
colorToGray(northWestPixel), 2 * colorToGray(northPixel), colorToGray(northEastPixel),
|
||||
0, 0, 0,
|
||||
-colorToGray(southWestPixel), -2 * colorToGray(southPixel), -colorToGray(southEastPixel),
|
||||
}
|
||||
|
||||
g_x := sumSlice(horizontalMatrix)
|
||||
g_y := sumSlice(verticalMatrix)
|
||||
|
||||
return math.Sqrt(
|
||||
math.Pow(g_x, 2) +
|
||||
math.Pow(g_y, 2),
|
||||
)
|
||||
}
|
35
main.go
Normal file
35
main.go
Normal file
@ -0,0 +1,35 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"image/png"
|
||||
_ "image/png"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Read image
|
||||
reader, _ := os.Open("./assets/surfer.png")
|
||||
rawImage, _, _ := image.Decode(reader)
|
||||
readImage := ImageAnalyzer{Image: rawImage}
|
||||
|
||||
bounds := readImage.Bounds()
|
||||
width := bounds.Max.X
|
||||
height := bounds.Max.Y
|
||||
writeImage := image.NewRGBA(bounds)
|
||||
|
||||
// Main action
|
||||
for x := range width {
|
||||
for y := range height {
|
||||
energy := uint8(readImage.CalculateEnergyAt(x, y))
|
||||
|
||||
color := color.RGBA{energy, energy, energy, 255}
|
||||
writeImage.Set(x, y, color)
|
||||
}
|
||||
}
|
||||
|
||||
// Out image
|
||||
writer, _ := os.Create("image.png")
|
||||
png.Encode(writer, writeImage)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user