Skip to content

Instantly share code, notes, and snippets.

@mAlishera
Created June 6, 2019 15:58
Show Gist options
  • Save mAlishera/8175238ba715a1de0787817a5211a745 to your computer and use it in GitHub Desktop.
Save mAlishera/8175238ba715a1de0787817a5211a745 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"image"
"image/png"
"log"
"math"
"os"
"gocv.io/x/gocv"
)
func main() {
if len(os.Args) < 2 {
fmt.Println("Enter .jpeg file path for image")
return
}
filename := os.Args[1]
window := gocv.NewWindow("Hello Katya")
img := gocv.IMRead(filename, gocv.IMReadGrayScale)
if img.Empty() {
fmt.Println("Error reading image from: %v", filename)
return
}
img1 := gocv.NewMat()
defer img1.Close()
// laba4 - laplacian, canny, sobel
gocv.Laplacian(img, &img1, 200, 5, 1, 0, gocv.BorderConstant)
gocv.Canny(img, &img1, 100, 200)
gocv.Sobel(img, &img1, 3, 0, 1, 7, 1, 0, gocv.BorderConstant)
src := loadImage("123.png")
if img, ok := src.(*image.NRGBA); ok {
dst1 := SobelFilter(img, 100)
dst2 := RobertsFilter(img, 100)
saveImage("sobel.png", dst1)
saveImage("roberts.png", dst2)
}
for {
window.IMShow(img1)
if window.WaitKey(1) >= 0 {
break
}
}
}
func loadImage(filename string) image.Image {
f, err := os.Open(filename)
if err != nil {
log.Fatalf("os.Open failed: %v", err)
}
defer f.Close()
img, _, err := image.Decode(f)
if err != nil {
log.Fatalf("image.Decode failed: %v", err)
}
return img
}
func saveImage(filename string, img image.Image) {
f, err := os.Create(filename)
if err != nil {
log.Fatalf("os.Create failed: %v", err)
}
defer f.Close()
err = png.Encode(f, img)
if err != nil {
log.Fatalf("png.Encode failed: %v", err)
}
}
type kernel [][]int32
var (
sobelKernelX = kernel{
{-1, 0, 1},
{-2, 0, 2},
{-1, 0, 1},
}
sobelkernelY = kernel{
{-1, -2, -1},
{0, 0, 0},
{1, 2, 1},
}
robertsKernelX = kernel{
{1, 0},
{0, -1},
}
robertsKernelY = kernel{
{0, 1},
{-1, 0},
}
)
func SobelFilter(img *image.NRGBA, threshold float64) *image.NRGBA {
var sumX, sumY int32
dx, dy := img.Bounds().Max.X, img.Bounds().Max.Y
dst := image.NewNRGBA(img.Bounds())
// окно 3x3 window of pixels because the image data given is just a 1D array of pixels
maxPixelOffset := dx*dy + len(sobelKernelX) - 1
data := getImageData(img)
length := len(data) - maxPixelOffset
magnitudes := make([]int32, length)
for i := 0; i < length; i++ {
// суммируем каждый пиксель со значением ядра
sumX, sumY = 0, 0
for x := 0; x < len(sobelKernelX); x++ {
for y := 0; y < len(sobelkernelY); y++ {
px := data[i+(dx*y)+x]
if len(px) > 0 {
r := px[0]
// нужно только значение px[0] (R) т.к картинка grayscale
sumX += int32(r) * sobelKernelX[y][x]
sumY += int32(r) * sobelkernelY[y][x]
}
}
}
magnitude := math.Sqrt(float64(sumX*sumX) + float64(sumY*sumY))
// проверяем цветовые границы пикселя
if magnitude < 0 {
magnitude = 0
} else if magnitude > 255 {
magnitude = 255
}
// magnitude <= threshold ? 0 : magnitude
if magnitude > threshold {
magnitudes[i] = int32(magnitude)
} else {
magnitudes[i] = 0
}
}
dataLength := dx * dy * 4
edges := make([]int32, dataLength)
// накладываем значения ядра
for i := 0; i < dataLength; i++ {
if i%4 != 0 {
m := magnitudes[i/4]
if m != 0 {
edges[i-1] = m
}
}
}
// генерим картинку с наложенным фильтром собеля
for idx := 0; idx < len(edges); idx += 4 {
dst.Pix[idx] = uint8(edges[idx])
dst.Pix[idx+1] = uint8(edges[idx+1])
dst.Pix[idx+2] = uint8(edges[idx+2])
dst.Pix[idx+3] = 255
}
return dst
}
func RobertsFilter(img *image.NRGBA, threshold float64) *image.NRGBA {
var sumX, sumY int32
dx, dy := img.Bounds().Max.X, img.Bounds().Max.Y
dst := image.NewNRGBA(img.Bounds())
// Get a 3x3 window of pixels because the image data given is just a 1D array of pixels
maxPixelOffset := dx*dy + len(robertsKernelX) - 1
data := getImageData(img)
length := len(data) - maxPixelOffset
magnitudes := make([]int32, length)
for i := 0; i < length; i++ {
// суммируем каждый пиксель со значением ядра
sumX, sumY = 0, 0
for x := 0; x < len(robertsKernelX); x++ {
for y := 0; y < len(robertsKernelY); y++ {
px := data[i+(dx*y)+x]
if len(px) > 0 {
r := px[0]
// нужно только значение px[0] (R) т.к картинка grayscale
sumX += int32(r) * robertsKernelX[y][x]
sumY += int32(r) * robertsKernelY[y][x]
}
}
}
magnitude := math.Sqrt(float64(sumX*sumX) + float64(sumY*sumY))
// проверяем цветовые границы пикселя
if magnitude < 0 {
magnitude = 0
} else if magnitude > 255 {
magnitude = 255
}
// magnitude <= threshold ? 0 : magnitude
if magnitude > threshold {
magnitudes[i] = int32(magnitude)
} else {
magnitudes[i] = 0
}
}
dataLength := dx * dy * 4
edges := make([]int32, dataLength)
// накладываем значения ядра
for i := 0; i < dataLength; i++ {
if i%4 != 0 {
m := magnitudes[i/4]
if m != 0 {
edges[i-1] = m
}
}
}
// генерим картинку с наложенным фильтром собеля
for idx := 0; idx < len(edges); idx += 4 {
dst.Pix[idx] = uint8(edges[idx])
dst.Pix[idx+1] = uint8(edges[idx+1])
dst.Pix[idx+2] = uint8(edges[idx+2])
dst.Pix[idx+3] = 255
}
return dst
}
// группируем пиксели в 2D массив, каждый содержит RGB значение пикселя.
func getImageData(img *image.NRGBA) [][]uint8 {
dx, dy := img.Bounds().Max.X, img.Bounds().Max.Y
pixels := make([][]uint8, dx*dy*4)
for i := 0; i < len(pixels); i += 4 {
pixels[i/4] = []uint8{
img.Pix[i],
img.Pix[i+1],
img.Pix[i+2],
img.Pix[i+3],
}
}
return pixels
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment