 — @Malakhor9000
 — @Malakhor9000
, , «» , Slack- .
«» — , Smite. , , . @Chrisbot. ., , , :
- .
- Slack.
- .
 image image/draw
image image/draw Go, , . №1.
, Slack- Go , Google. Go Slack , , , , Slack. №2.
, — . 
golang face detect — StackOverflow 
go-opencv. 
, . №3.
. , , «» .
go-opencv. , opencv Go, Image Rectangle, , .
, opencv.FromImage, image.Image opencv . , opencv.LoadImage, , . Slack.
, XML- Haar , , . facefinder, :
package facefinder
import (
  "image"
  "github.com/lazywei/go-opencv/opencv"
)
var faceCascade *opencv.HaarCascade
type Finder struct {
  cascade *opencv.HaarCascade
}
func NewFinder(xml string) *Finder {
  return &Finder{
    cascade: opencv.LoadHaarClassifierCascade(xml),
  }
}
func (f *Finder) Detect(i image.Image) []image.Rectangle {
  var output []image.Rectangle
  faces := f.cascade.DetectObjects(opencv.FromImage(i))
  for _, face := range faces {
    output = append(output, image.Rectangle{
      image.Point{face.X(), face.Y()},
      image.Point{face.X() + face.Width(), face.Y() + face.Height()},
    })
  }
  return output
}
, :
imageReader, _ := os.Open(imageFile)
baseImage, _, _ := image.Decode(imageReader)
finder := facefinder.NewFinder(haarCascadeFilepath)
faces := finder.Detect(baseImage)
for _, face := range faces {
  
}
! , . , _ bin.
func loadImage(file string) image.Image {
  reader, err := os.Open(file)
  if err != nil {
    log.Fatalf("error loading %s: %s", file, err)
  }
  img, _, err := image.Decode(reader)
  if err != nil {
    log.Fatalf("error loading %s: %s", file, err)
  }
  return img
}
- :
baseImage := loadImage(imageFile)
chrisFace := loadImage(chrisFaceFile)
bounds := baseImage.Bounds()
finder := facefinder.NewFinder(haarCascadeFilepath)
faces := finder.Detect(baseImage)
canvas := image.NewRGBA(bounds)
draw.Draw(canvas, bounds, baseImage, bounds.Min, draw.Src)
for _, face := range faces {
  draw.Draw(
    canvas,
    face,
    chrisFace,
    bounds.Min,
    draw.Src,
  )
}
, , !

, . ! . PNG , . draw.Over draw.Draw. draw.Src !

, , , 
, — , .
, . , - . , , «», - . , image.Rectangle , «» 30%.
, « » , «» . , 
disintegration/imaging, imaging.Fit , , , . , , .
:
for _, face := range faces {
  
  rect := rectMargin(30.0, face)
  
  newFace := chrisFaces.Random()
  chrisFace := imaging.Fit(newFace, rect.Dx(), rect.Dy(), imaging.Lanczos)
  draw.Draw(
    canvas,
    rect,
    chrisFace,
    bounds.Min,
    draw.Over,
  )
}
, , … !

: - .
Slack
, Slack-. , , Slack-. « » Slack-, .
Google.
, 
, , . Slack API, , . :

Slack, Slack . , , Slack . Slack , , , .
. , , , . ! - :
if len(faces) == 0 {
  
  
  face := imaging.Resize(
    chrisFaces[0],
    bounds.Dx()/3,
    0,
    imaging.Lanczos,
  )
  face_bounds := face.Bounds()
  draw.Draw(
    canvas,
    bounds,
    face,
    
    
    
    bounds.Min.Add(image.Pt(
      -bounds.Max/2+face_bounds.Max.X/2,
      -bounds.Max.Y+int(float64(face_bounds.Max.Y)/1.9),
    )),
    draw.Over,
  )
}
:

- , .
, , ? , , .
@Chrisbot

— , ! , , .
— Chrisbot @jhutchinson.
«» .

— ?
—
— , - , .
, , .
, .

@Chrisbot’.







, , . — , go-opencv, , .
, «» Slack’e, , , - «».

— , , . !
: .
 https://github.com/zikes/chrisifyhttps://github.com/zikes/mybot
https://github.com/zikes/chrisifyhttps://github.com/zikes/mybot