Created
June 6, 2019 15:58
-
-
Save mAlishera/8175238ba715a1de0787817a5211a745 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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