thuja

social media without the bullshit
git clone git://kqueue.dev/thuja.git
Log | Files | Refs | README | LICENSE

region.go (2850B)


      1 package nude
      2 
      3 import (
      4 	"math"
      5 )
      6 
      7 type Pixel struct {
      8 	id      int
      9 	isSkin  bool
     10 	region  int
     11 	X       int
     12 	Y       int
     13 	chekced bool
     14 	V       float64 // intesitiy(Value) of HSV
     15 }
     16 
     17 // TODO: cache caluculated leftMost, rightMost, upperMost, lowerMost.
     18 type Region []*Pixel
     19 
     20 // TODO: optimize
     21 //func (r Region) isSkin(x, y int) bool {
     22 //	for _, pixel := range r {
     23 //		if pixel.isSkin && pixel.X == x && pixel.Y == y {
     24 //			return true
     25 //		}
     26 //	}
     27 //	return false
     28 //}
     29 
     30 func (r Region) leftMost() *Pixel {
     31 	minX := math.MaxInt32
     32 	index := 0
     33 	for i, pixel := range r {
     34 		if pixel.X < minX {
     35 			minX = pixel.X
     36 			index = i
     37 		}
     38 	}
     39 	return r[index]
     40 }
     41 
     42 func (r Region) rightMost() *Pixel {
     43 	maxX := math.MinInt32
     44 	index := 0
     45 	for i, pixel := range r {
     46 		if pixel.X > maxX {
     47 			maxX = pixel.X
     48 			index = i
     49 		}
     50 	}
     51 	return r[index]
     52 }
     53 
     54 func (r Region) upperMost() *Pixel {
     55 	minY := math.MaxInt32
     56 	index := 0
     57 	for i, pixel := range r {
     58 		if pixel.Y < minY {
     59 			minY = pixel.Y
     60 			index = i
     61 		}
     62 	}
     63 	return r[index]
     64 }
     65 
     66 func (r Region) lowerMost() *Pixel {
     67 	maxY := math.MinInt32
     68 	index := 0
     69 	for i, pixel := range r {
     70 		if pixel.Y > maxY {
     71 			maxY = pixel.Y
     72 			index = i
     73 		}
     74 	}
     75 	return r[index]
     76 }
     77 
     78 func (r Region) skinRateInBoundingPolygon() float64 {
     79 	// build the bounding polygon by the regions edge values:
     80 	// Identify the leftmost, the uppermost, the rightmost, and the lowermost skin pixels of the three largest skin regions.
     81 	// Use these points as the corner points of a bounding polygon.
     82 	left := r.leftMost()
     83 	right := r.rightMost()
     84 	upper := r.upperMost()
     85 	lower := r.lowerMost()
     86 	vertices := []*Pixel{left, upper, right, lower, left}
     87 	total := 0
     88 	skin := 0
     89 
     90 	// via http://katsura-kotonoha.sakura.ne.jp/prog/c/tip0002f.shtml
     91 	for _, p1 := range r {
     92 		inPolygon := true
     93 		for i := 0; i < len(vertices)-1; i++ {
     94 			p2 := vertices[i]
     95 			p3 := vertices[i+1]
     96 			n := p1.X*(p2.Y-p3.Y) + p2.X*(p3.Y-p1.Y) + p3.X*(p1.Y-p2.Y)
     97 			if n < 0 {
     98 				inPolygon = false
     99 				break
    100 			}
    101 		}
    102 		if inPolygon && p1.isSkin {
    103 			skin = skin + 1
    104 		}
    105 		total = total + 1
    106 	}
    107 	return float64(skin) / float64(total)
    108 }
    109 
    110 func (r Region) averageIntensity() float64 {
    111 	var totalIntensity float64
    112 	for _, pixel := range r {
    113 		totalIntensity = totalIntensity + pixel.V
    114 	}
    115 	return totalIntensity / float64(len(r))
    116 }
    117 
    118 type Regions []Region
    119 
    120 func (r Regions) totalPixels() int {
    121 	var totalSkin int
    122 	for _, pixels := range r {
    123 		totalSkin += len(pixels)
    124 	}
    125 	return totalSkin
    126 }
    127 
    128 func (r Regions) averageIntensity() float64 {
    129 	var totalIntensity float64
    130 	for _, region := range r {
    131 		totalIntensity = totalIntensity + region.averageIntensity()
    132 	}
    133 	return totalIntensity / float64(len(r))
    134 }
    135 
    136 //
    137 // sort interface
    138 //
    139 
    140 func (r Regions) Len() int {
    141 	return len(r)
    142 }
    143 
    144 func (r Regions) Swap(i, j int) {
    145 	r[i], r[j] = r[j], r[i]
    146 }
    147 
    148 func (r Regions) Less(i, j int) bool {
    149 	return len(r[i]) < len(r[j])
    150 }