@ -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 |
@ -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
|
|||
} |
@ -0,0 +1,4 @@ |
|||
{ |
|||
"imgWidth": 300, |
|||
"imgHeigh": 300 |
|||
} |
@ -0,0 +1,9 @@ |
|||
package main |
|||
|
|||
import "fmt" |
|||
|
|||
func check(err error) { |
|||
if err != nil { |
|||
fmt.Println(err) |
|||
} |
|||
} |
@ -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 |
|||
} |
@ -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 |
|||
} |
@ -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) |
|||
|
|||
} |
@ -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) |
|||
} |
@ -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 |
|||
} |