mirror of
https://github.com/arnaucube/galdric.git
synced 2026-02-06 18:56:45 +01:00
it works!
This commit is contained in:
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
datasets
|
||||
dataset
|
||||
dataset_complet
|
||||
*.jpg
|
||||
*.jpeg
|
||||
*.png
|
||||
@@ -1,2 +1,10 @@
|
||||
# galdric
|
||||
machine learning server, for image classification
|
||||
|
||||
|
||||
|
||||
- Reads all the datasets in the folder /dataset
|
||||
- Each image is resized to the same size, configured in the config.json
|
||||
- For the input images, calculates the euclidean distances
|
||||
- Gets the nearest neighbour
|
||||
- Show the result, that is the label of the object in the image
|
||||
|
||||
57
color.go
Normal file
57
color.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
//Color struct, defines the color
|
||||
type Color struct{}
|
||||
|
||||
var c Color
|
||||
|
||||
//DarkGray color
|
||||
func (c Color) DarkGray(t string) {
|
||||
fmt.Print("\x1b[30;1m") //dark gray
|
||||
fmt.Println(t)
|
||||
fmt.Print("\x1b[0m") //defaultColor
|
||||
}
|
||||
|
||||
//Red color
|
||||
func (c Color) Red(t string) {
|
||||
fmt.Print("\x1b[31;1m") //red
|
||||
fmt.Println(t)
|
||||
fmt.Print("\x1b[0m") //defaultColor
|
||||
}
|
||||
|
||||
//Green color
|
||||
func (c Color) Green(t string) {
|
||||
fmt.Print("\x1b[32;1m") //green
|
||||
fmt.Println(t)
|
||||
fmt.Print("\x1b[0m") //defaultColor
|
||||
}
|
||||
|
||||
//Yellow color
|
||||
func (c Color) Yellow(t string) {
|
||||
fmt.Print("\x1b[33;1m") //yellow
|
||||
fmt.Println(t)
|
||||
fmt.Print("\x1b[0m") //defaultColor
|
||||
}
|
||||
|
||||
//Blue color
|
||||
func (c Color) Blue(t string) {
|
||||
fmt.Print("\x1b[34;1m") //blue
|
||||
fmt.Println(t)
|
||||
fmt.Print("\x1b[0m") //defaultColor
|
||||
}
|
||||
|
||||
//Purple color
|
||||
func (c Color) Purple(t string) {
|
||||
fmt.Print("\x1b[35;1m") //purple
|
||||
fmt.Println(t)
|
||||
fmt.Print("\x1b[0m") //defaultColor
|
||||
}
|
||||
|
||||
//Cyan color
|
||||
func (c Color) Cyan(t string) {
|
||||
fmt.Print("\x1b[36;1m") //cyan
|
||||
fmt.Println(t)
|
||||
fmt.Print("\x1b[0m") //defaultColor
|
||||
}
|
||||
4
config.json
Normal file
4
config.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"imgWidth": 300,
|
||||
"imgHeigh": 300
|
||||
}
|
||||
9
errors.go
Normal file
9
errors.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func check(err error) {
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
85
imageOperations.go
Normal file
85
imageOperations.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"image"
|
||||
"image/jpeg"
|
||||
"image/png"
|
||||
|
||||
"github.com/nfnt/resize"
|
||||
)
|
||||
|
||||
type imgRGBA [][]float64
|
||||
|
||||
func dataToImage(data []byte, imageName string) (image.Image, error) {
|
||||
//var histogram imgRGBA
|
||||
reader := bytes.NewReader(data)
|
||||
//var imageExtension = strings.Split(imageName, ".")[1]
|
||||
var img image.Image
|
||||
var err error
|
||||
/*switch imageExtension {
|
||||
case "png":
|
||||
img, err = png.Decode(reader)
|
||||
case "jpg":
|
||||
img, err = jpeg.Decode(reader)
|
||||
case "jpeg":
|
||||
img, err = jpeg.Decode(reader)
|
||||
default:
|
||||
img = nil
|
||||
}
|
||||
*/
|
||||
img, err = jpeg.Decode(reader)
|
||||
if err != nil {
|
||||
return img, err
|
||||
}
|
||||
return img, err
|
||||
}
|
||||
|
||||
func imageToData(img image.Image, imageName string) ([]byte, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
//var imageExtension = strings.Split(imageName, ".")[1]
|
||||
var err error
|
||||
/*switch imageExtension {
|
||||
case "png":
|
||||
err = png.Encode(buf, img)
|
||||
case "jpg":
|
||||
err = jpeg.Encode(buf, img, nil)
|
||||
case "jpeg":
|
||||
err = jpeg.Encode(buf, img, nil)
|
||||
default:
|
||||
img = nil
|
||||
}*/
|
||||
err = jpeg.Encode(buf, img, nil)
|
||||
if err != nil {
|
||||
return buf.Bytes(), err
|
||||
}
|
||||
return buf.Bytes(), err
|
||||
}
|
||||
|
||||
func imageToPNG(img image.Image) ([]byte, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
var err error
|
||||
err = png.Encode(buf, img)
|
||||
return buf.Bytes(), err
|
||||
}
|
||||
|
||||
func imageToHistogram(img image.Image) [][]float64 {
|
||||
bounds := img.Bounds()
|
||||
|
||||
//generate the histogram
|
||||
var histogram [][]float64
|
||||
for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
|
||||
for x := bounds.Min.X; x < bounds.Max.X; x++ {
|
||||
r, g, b, a := img.At(x, y).RGBA()
|
||||
var pixel []float64
|
||||
pixel = append(pixel, float64(r), float64(g), float64(b), float64(a))
|
||||
histogram = append(histogram, pixel)
|
||||
}
|
||||
}
|
||||
return histogram
|
||||
}
|
||||
|
||||
func Resize(img image.Image) image.Image {
|
||||
r := resize.Resize(uint(config.ImgWidth), uint(config.ImgHeigh), img, resize.Lanczos3)
|
||||
return r
|
||||
}
|
||||
30
knn.go
Normal file
30
knn.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package main
|
||||
|
||||
func euclideanDist(img1, img2 [][]float64) float64 {
|
||||
var dist float64
|
||||
|
||||
for i := 0; i < len(img1); i++ {
|
||||
for j := 0; j < len(img1[i]); j++ {
|
||||
dist += (img1[i][j] - img2[i][j]) * (img1[i][j] - img2[i][j])
|
||||
}
|
||||
}
|
||||
|
||||
return dist
|
||||
}
|
||||
|
||||
func knn(dataset Dataset, input [][]float64) string {
|
||||
d := euclideanDist(dataset["Leopards"][0], input)
|
||||
label := "lamp"
|
||||
for k, v := range dataset {
|
||||
//fmt.Println(k)
|
||||
for i := 0; i < len(v); i++ {
|
||||
//fmt.Println(i)
|
||||
dNew := euclideanDist(v[i], input)
|
||||
if dNew < d {
|
||||
d = dNew
|
||||
label = k
|
||||
}
|
||||
}
|
||||
}
|
||||
return label
|
||||
}
|
||||
31
main.go
Normal file
31
main.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
readConfig("./config.json")
|
||||
|
||||
c.Cyan("reading images datasets")
|
||||
tStart := time.Now()
|
||||
dataset := readDataset("./dataset")
|
||||
fmt.Print("time spend reading images: ")
|
||||
fmt.Println(time.Since(tStart))
|
||||
fmt.Println("total folders scanned: " + strconv.Itoa(len(dataset)))
|
||||
|
||||
numImages := 0
|
||||
for _, v := range dataset {
|
||||
numImages = numImages + len(v)
|
||||
}
|
||||
c.Cyan("total images in dataset: " + strconv.Itoa(numImages))
|
||||
|
||||
//we have the images in the dataset variable
|
||||
//now, can take images
|
||||
testFile := readImage("./test.jpg")
|
||||
r := knn(dataset, testFile)
|
||||
fmt.Println("seems to be a " + r)
|
||||
|
||||
}
|
||||
23
readConfig.go
Normal file
23
readConfig.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
ImgWidth int `json:"imgWidth"`
|
||||
ImgHeigh int `json:"imgHeigh"`
|
||||
}
|
||||
|
||||
var config Config
|
||||
|
||||
func readConfig(path string) {
|
||||
file, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
fmt.Println("error: ", err)
|
||||
}
|
||||
content := string(file)
|
||||
json.Unmarshal([]byte(content), &config)
|
||||
}
|
||||
74
readDataset.go
Normal file
74
readDataset.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
//each image is [][]float64, is a array of pixels
|
||||
type ImgDataset [][][]float64
|
||||
|
||||
type Dataset map[string]ImgDataset
|
||||
|
||||
func byteArrayToFloat64Array(b []byte) []float64 {
|
||||
var f []float64
|
||||
for i := 0; i < len(b); i++ {
|
||||
val, _ := strconv.ParseFloat(string(b[i]), 64)
|
||||
/*fmt.Print(string(b[i]) + "-")
|
||||
fmt.Println(val)*/
|
||||
f = append(f, val)
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func readImage(path string) [][]float64 {
|
||||
//open image file
|
||||
/*reader, err := os.Open(path)
|
||||
check(err)
|
||||
defer reader.Close()*/
|
||||
|
||||
dat, err := ioutil.ReadFile(path)
|
||||
check(err)
|
||||
|
||||
imageRaw, err := dataToImage(dat, path)
|
||||
check(err)
|
||||
|
||||
//resize the image to standard size
|
||||
image := Resize(imageRaw)
|
||||
|
||||
//convert the image to histogram(RGBA)
|
||||
histogram := imageToHistogram(image)
|
||||
//convert image to bytes
|
||||
/*imgBytes, err := imageToData(image, path)
|
||||
check(err)*/
|
||||
|
||||
//imgFloat := byteArrayToFloat64Array(imgBytes)
|
||||
return histogram
|
||||
}
|
||||
func readDataset(path string) map[string]ImgDataset {
|
||||
//dataset := make(map[string]ImgDataset)
|
||||
dataset := make(Dataset)
|
||||
|
||||
folders, _ := ioutil.ReadDir(path)
|
||||
for _, folder := range folders {
|
||||
fmt.Println(folder.Name())
|
||||
|
||||
var imgDataset ImgDataset
|
||||
|
||||
folderFiles, _ := ioutil.ReadDir(path + "/" + folder.Name())
|
||||
for _, file := range folderFiles {
|
||||
image := readImage(path + "/" + folder.Name() + "/" + file.Name())
|
||||
|
||||
imgDataset = append(imgDataset, image)
|
||||
|
||||
/*fmt.Println(folder.Name())
|
||||
fmt.Println(file.Name())*/
|
||||
}
|
||||
|
||||
//add the foldername to the Dataset map
|
||||
dataset[folder.Name()] = imgDataset
|
||||
}
|
||||
|
||||
return dataset
|
||||
}
|
||||
Reference in New Issue
Block a user