Skip to content

Commit

Permalink
Segments are now represented as an int instead of multiple bools.
Browse files Browse the repository at this point in the history
  • Loading branch information
dhogborg committed Jul 14, 2016
1 parent 369b110 commit c1c3f01
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 90 deletions.
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ build_linux:

package: build_linux
docker build -t dhogborg/gosser:latest .

push:
docker push dhogborg/gosser:latest

lint:
golint .
Expand Down
186 changes: 96 additions & 90 deletions internal/ssocr/ssocr.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,11 @@ func (s *SSOCR) Scan(imagefile string) string {
segm := s.extractPosition(img, a)
var position *SsDigit

if len(predefs) == 0 {
position = NewSsDigit(segm)
} else {
if len(predefs) > a {
position = predefs[a]
position.Image = segm
} else {
position = NewSsDigit(segm)
}

position.Position = a
Expand Down Expand Up @@ -112,45 +112,53 @@ func (s *SSOCR) extractPosition(img image.Image, position int) image.Image {
bounds := img.Bounds()
rgba := image.NewRGBA(bounds)

// copy the generic image data to a greyscale image model
if g, ok := copyImage(img, rgba).(*image.RGBA); ok {
rgba = g
}
copyImage(img, rgba)

segmentWidth := int(float64(bounds.Dx()) / float64(s.Positions))
segmentInset := int(float64(segmentWidth) * float64(position))

// extract a subimage with the positions inset
subrect := image.Rect(bounds.Min.X+segmentInset, bounds.Min.Y, bounds.Min.X+segmentInset+segmentWidth, bounds.Max.Y)
subrect := image.Rect(
bounds.Min.X+segmentInset,
bounds.Min.Y,
bounds.Min.X+segmentInset+segmentWidth,
bounds.Max.Y,
)

return rgba.SubImage(subrect)
}

// Direction identifiers
const (
North = iota
South = iota
West = iota
East = iota
)

// Segment identifiers
const (
NorthPole = 1 << iota // 1
NorthWest = 1 << iota // 2
NorthEast = 1 << iota // 4
Equator = 1 << iota // 8
SouthWest = 1 << iota // 16
SouthEast = 1 << iota // 32
SouthPole = 1 << iota // 64
)

// SsDigit has a position (n:th digit in image), a north and a south origin,
// and segments added together for charater matching.
type SsDigit struct {
Position int
Image image.Image

NorthPoint []int `json:"north"`
SouthPoint []int `json:"south"`

// segments
NorthPole bool
NorthWest bool
NorthEast bool

Equator bool

SouthWest bool
SouthEast bool
SouthPole bool
Segments int
}

const (
NORTH = iota
SOUTH = iota
WEST = iota
EAST = iota
)

func NewSsDigit(img image.Image) *SsDigit {
return &SsDigit{
Image: img,
Expand Down Expand Up @@ -183,12 +191,20 @@ func (s *SsDigit) Scan() {
"base_value": nBaseValue,
}).Debug("North origin")

s.NorthPole = s.isActiveSegment(nBaseValue, s.minValue(northOrigin, quarterHeight, NORTH))
s.NorthWest = s.isActiveSegment(nBaseValue, s.minValue(northOrigin, quarterWidth, WEST))
s.NorthEast = s.isActiveSegment(nBaseValue, s.minValue(northOrigin, quarterWidth, EAST))
if s.isActiveSegment(nBaseValue, s.minValue(northOrigin, quarterHeight, North)) {
s.Segments += NorthPole
}
if s.isActiveSegment(nBaseValue, s.minValue(northOrigin, quarterWidth, West)) {
s.Segments += NorthWest
}
if s.isActiveSegment(nBaseValue, s.minValue(northOrigin, quarterWidth, East)) {
s.Segments += NorthEast
}

// center, use north origin
s.Equator = s.isActiveSegment(nBaseValue, s.minValue(northOrigin, quarterHeight, SOUTH))
if s.isActiveSegment(nBaseValue, s.minValue(northOrigin, quarterHeight, South)) {
s.Segments += Equator
}

// South origin points
// the south is slanted to the left
Expand All @@ -208,9 +224,15 @@ func (s *SsDigit) Scan() {
"base_value": sBaseValue,
}).Debug("South origin")

s.SouthWest = s.isActiveSegment(sBaseValue, s.minValue(southOrigin, quarterWidth, WEST))
s.SouthEast = s.isActiveSegment(sBaseValue, s.minValue(southOrigin, quarterWidth, EAST))
s.SouthPole = s.isActiveSegment(sBaseValue, s.minValue(southOrigin, quarterHeight, SOUTH))
if s.isActiveSegment(sBaseValue, s.minValue(southOrigin, quarterWidth, West)) {
s.Segments += SouthWest
}
if s.isActiveSegment(sBaseValue, s.minValue(southOrigin, quarterWidth, East)) {
s.Segments += SouthEast
}
if s.isActiveSegment(sBaseValue, s.minValue(southOrigin, quarterHeight, South)) {
s.Segments += SouthPole
}

// debug output the segments
if DEBUG {
Expand All @@ -232,24 +254,23 @@ func (s *SsDigit) isActiveSegment(baseValue, crossValue uint32) bool {

func (s *SsDigit) String() string {

characters := map[string]*SsDigit{
"0": &SsDigit{NorthPole: true, NorthWest: true, NorthEast: true, SouthWest: true, SouthEast: true, SouthPole: true},
"1": &SsDigit{NorthEast: true, SouthEast: true},
"2": &SsDigit{NorthPole: true, NorthEast: true, Equator: true, SouthWest: true, SouthPole: true},
"3": &SsDigit{NorthPole: true, NorthEast: true, Equator: true, SouthEast: true, SouthPole: true},
"4": &SsDigit{NorthWest: true, NorthEast: true, Equator: true, SouthEast: true},
"5": &SsDigit{NorthPole: true, NorthWest: true, Equator: true, SouthEast: true, SouthPole: true},
"6": &SsDigit{NorthPole: true, NorthWest: true, Equator: true, SouthWest: true, SouthEast: true, SouthPole: true},
"7": &SsDigit{NorthPole: true, NorthEast: true, SouthEast: true},
"8": &SsDigit{NorthPole: true, NorthWest: true, NorthEast: true, Equator: true, SouthWest: true, SouthEast: true, SouthPole: true},
"9": &SsDigit{NorthPole: true, NorthWest: true, NorthEast: true, Equator: true, SouthEast: true},
}

for c, d := range characters {
if s.Equals(d) {
return c
}
characters := map[int]string{
NorthPole + NorthEast + NorthWest + SouthEast + SouthWest + SouthPole: "0",
NorthEast + SouthEast: "1",
NorthPole + NorthEast + Equator + SouthWest + SouthPole: "2",
NorthPole + NorthEast + Equator + SouthEast + SouthPole: "3",
NorthEast + NorthWest + Equator + SouthEast: "4",
NorthPole + NorthWest + Equator + SouthEast + SouthPole: "5",
NorthPole + NorthWest + Equator + SouthEast + SouthWest + SouthPole: "6",
NorthPole + NorthEast + SouthEast: "7",
NorthPole + NorthEast + NorthWest + Equator + SouthEast + SouthWest + SouthPole: "8",
NorthPole + NorthEast + NorthWest + Equator + SouthWest + SouthPole: "9",
}

if c, ok := characters[s.Segments]; ok {
return c
}

return "-"
}

Expand All @@ -261,7 +282,7 @@ func (s *SsDigit) AppendTo(lines []string) []string {

pl := s.Dotstrings()
for i := range lines {
lines[i] += pl[i] + " "
lines[i] += pl[i] + " "
}
return lines
}
Expand All @@ -281,76 +302,60 @@ func (s *SsDigit) Dotstrings() []string {
[]string{" ", " ", " "},
[]string{" ", " ", " "},
}

if s.NorthPole {
if (s.Segments & NorthPole) == NorthPole {
dots[0] = []string{"*", "*", "*"}
}
if s.NorthWest {
if (s.Segments & NorthWest) == NorthWest {
dots[0][0] = "*"
dots[1][0] = "*"
dots[2][0] = "*"
}
if s.NorthEast {
if (s.Segments & NorthEast) == NorthEast {
dots[0][2] = "*"
dots[1][2] = "*"
dots[2][2] = "*"
}
if s.Equator {
if (s.Segments & Equator) == Equator {
dots[2] = []string{"*", "*", "*"}
}
if s.SouthWest {
if (s.Segments & SouthWest) == SouthWest {
dots[2][0] = "*"
dots[3][0] = "*"
dots[4][0] = "*"
}
if s.SouthEast {
if (s.Segments & SouthEast) == SouthEast {
dots[2][2] = "*"
dots[3][2] = "*"
dots[4][2] = "*"
}
if s.SouthPole {
if (s.Segments & SouthPole) == SouthPole {
dots[4] = []string{"*", "*", "*"}
}

lines := []string{}
for _, l := range dots {
lines = append(lines, strings.Join(l, ""))
lines = append(lines, strings.Join(l, " "))
}

return lines
}

// Equals returns true if the receiver and compration
// object have the same segment configuration
func (s *SsDigit) Equals(comp *SsDigit) bool {
return (s.NorthPole == comp.NorthPole) &&
(s.NorthWest == comp.NorthWest) &&
(s.NorthEast == comp.NorthEast) &&
(s.Equator == comp.Equator) &&
(s.SouthWest == comp.SouthWest) &&
(s.SouthEast == comp.SouthEast) &&
(s.SouthPole == comp.SouthPole)
}

func (s *SsDigit) minValue(origin image.Point, length, direction int) uint32 {

// Direction legend:
// North: origin.Y--
// West: origin.X--
// East: origin.X++
// South: origin.Y++
directionMap := map[int]image.Point{
NORTH: image.Point{X: 0, Y: -1},
WEST: image.Point{X: -1, Y: 0},
EAST: image.Point{X: 1, Y: 0},
SOUTH: image.Point{X: 0, Y: 1},
North: image.Point{X: 0, Y: -1},
West: image.Point{X: -1, Y: 0},
East: image.Point{X: 1, Y: 0},
South: image.Point{X: 0, Y: 1},
}

bounds := s.Image.Bounds()
point := origin
pointMod := directionMap[direction]
img := s.Image
bounds := img.Bounds()

minValue, _, _, _ := s.Image.At(point.X, point.Y).RGBA()

for a := 0; a < length; a++ {
point = point.Add(pointMod)

Expand All @@ -362,20 +367,23 @@ func (s *SsDigit) minValue(origin image.Point, length, direction int) uint32 {
break
}

pValue, _, _, _ := s.Image.At(point.X, point.Y).RGBA()
// minValue = (minValue + pValue) / 2
if minValue > pValue {
minValue = pValue
red, _, _, _ := img.At(point.X, point.Y).RGBA()
if minValue > red {
minValue = red
}

if DEBUG {
if img, ok := s.Image.(*image.RGBA); ok {
img.Set(point.X, point.Y, color.RGBA{uint8(pValue), 255, 0, 255})
img.Set(point.X, point.Y, color.RGBA{uint8(red), 255, 0, 255})
}
}

}

log.WithFields(log.Fields{
"value": minValue,
"dir": direction,
}).Info("minvalue")

return minValue
}

Expand All @@ -388,7 +396,7 @@ type imageTarget interface {

// copyImage copies the contents of source to target
// converting the color to the target color model.
func copyImage(source image.Image, target imageTarget) imageTarget {
func copyImage(source image.Image, target imageTarget) {
b := source.Bounds()
for y := b.Min.Y; y < b.Max.Y; y++ {
for x := b.Min.X; x < b.Max.X; x++ {
Expand All @@ -397,6 +405,4 @@ func copyImage(source image.Image, target imageTarget) imageTarget {
target.Set(x, y, color)
}
}

return target
}

0 comments on commit c1c3f01

Please sign in to comment.