Skip to content

Commit

Permalink
rename Analyzer to Detector
Browse files Browse the repository at this point in the history
  • Loading branch information
koyachi committed May 7, 2014
1 parent dc6d6b8 commit 3452ee5
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 78 deletions.
8 changes: 4 additions & 4 deletions example/region/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,12 @@ func main() {
//imagePath := "../images/test2.jpg"
//imagePath := "../images/test6.jpg"

n := nude.New(imagePath)
isNude, err := n.Parse()
d := nude.NewDetector(imagePath)
isNude, err := d.Parse()
if err != nil {
log.Fatal(err)
}
fmt.Printf("isNude = %v\n", isNude)
fmt.Printf("%s\n", n)
drawImageAndRegions(imagePath, n.SkinRegions)
fmt.Printf("%s\n", d)
drawImageAndRegions(imagePath, d.SkinRegions)
}
148 changes: 74 additions & 74 deletions nude.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ func IsNude(imageFilePath string) (result bool, err error) {
if err != nil {
return false, err
}
a := New(path)
result, err = a.Parse()
d := NewDetector(path)
result, err = d.Parse()

return
}
Expand Down Expand Up @@ -52,7 +52,7 @@ func decodeImage(filePath string) (img image.Image, err error) {
return
}

type Analyzer struct {
type Detector struct {
filePath string
image image.Image
width int
Expand All @@ -68,40 +68,40 @@ type Analyzer struct {
result bool
}

func New(path string) *Analyzer {
analyzer := &Analyzer{
func NewDetector(path string) *Detector {
d := &Detector{
filePath: path,
}
return analyzer
return d
}

func (a *Analyzer) Parse() (result bool, err error) {
img, err := decodeImage(a.filePath)
func (d *Detector) Parse() (result bool, err error) {
img, err := decodeImage(d.filePath)
if err != nil {
return false, err
}
bounds := img.Bounds()
a.image = img
a.width = bounds.Size().X
a.height = bounds.Size().Y
a.lastFrom = -1
a.lastTo = -1
a.totalPixels = a.width * a.height
d.image = img
d.width = bounds.Size().X
d.height = bounds.Size().Y
d.lastFrom = -1
d.lastTo = -1
d.totalPixels = d.width * d.height

for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
width := bounds.Size().X
for x := bounds.Min.X; x < bounds.Max.X; x++ {
r, g, b, _ := a.image.At(x, y).RGBA()
r, g, b, _ := d.image.At(x, y).RGBA()
normR := r / 256
normG := g / 256
normB := b / 256
currentIndex := x + y*width
nextIndex := currentIndex + 1

if !classifySkin(normR, normG, normB) {
a.skinMap = append(a.skinMap, &Skin{currentIndex, false, 0, x, y, false})
d.skinMap = append(d.skinMap, &Skin{currentIndex, false, 0, x, y, false})
} else {
a.skinMap = append(a.skinMap, &Skin{currentIndex, true, 0, x, y, false})
d.skinMap = append(d.skinMap, &Skin{currentIndex, true, 0, x, y, false})

region := -1
checkIndexes := []int{
Expand All @@ -116,50 +116,50 @@ func (a *Analyzer) Parse() (result bool, err error) {
if checkIndex < 0 {
continue
}
skin := a.skinMap[checkIndex]
skin := d.skinMap[checkIndex]
if skin != nil && skin.skin {
if skin.region != region &&
region != -1 &&
a.lastFrom != region &&
a.lastTo != skin.region {
a.addMerge(region, skin.region)
d.lastFrom != region &&
d.lastTo != skin.region {
d.addMerge(region, skin.region)
}
region = a.skinMap[checkIndex].region
region = d.skinMap[checkIndex].region
checker = true
}
}

if !checker {
a.skinMap[currentIndex].region = len(a.detectedRegions)
a.detectedRegions = append(a.detectedRegions, []*Skin{a.skinMap[currentIndex]})
d.skinMap[currentIndex].region = len(d.detectedRegions)
d.detectedRegions = append(d.detectedRegions, []*Skin{d.skinMap[currentIndex]})
continue
} else {
if region > -1 {
if len(a.detectedRegions) >= region {
a.detectedRegions = append(a.detectedRegions, SkinMap{})
if len(d.detectedRegions) >= region {
d.detectedRegions = append(d.detectedRegions, SkinMap{})
}
a.skinMap[currentIndex].region = region
a.detectedRegions[region] = append(a.detectedRegions[region], a.skinMap[currentIndex])
d.skinMap[currentIndex].region = region
d.detectedRegions[region] = append(d.detectedRegions[region], d.skinMap[currentIndex])
}
}
}
}
}

a.merge(a.detectedRegions, a.mergeRegions)
a.analyzeRegions()
d.merge(d.detectedRegions, d.mergeRegions)
d.analyzeRegions()

return a.result, err
return d.result, err
}

func (a *Analyzer) addMerge(from, to int) {
a.lastFrom = from
a.lastTo = to
func (d *Detector) addMerge(from, to int) {
d.lastFrom = from
d.lastTo = to

fromIndex := -1
toIndex := -1

for index, region := range a.mergeRegions {
for index, region := range d.mergeRegions {
for _, regionIndex := range region {
if regionIndex == from {
fromIndex = index
Expand All @@ -172,34 +172,34 @@ func (a *Analyzer) addMerge(from, to int) {

if fromIndex != -1 && toIndex != -1 {
if fromIndex != toIndex {
fromRegion := a.mergeRegions[fromIndex]
toRegion := a.mergeRegions[toIndex]
fromRegion := d.mergeRegions[fromIndex]
toRegion := d.mergeRegions[toIndex]
region := append(fromRegion, toRegion...)
a.mergeRegions[fromIndex] = region
a.mergeRegions = append(a.mergeRegions[:toIndex], a.mergeRegions[toIndex+1:]...)
d.mergeRegions[fromIndex] = region
d.mergeRegions = append(d.mergeRegions[:toIndex], d.mergeRegions[toIndex+1:]...)
}
return
}

if fromIndex == -1 && toIndex == -1 {
a.mergeRegions = append(a.mergeRegions, []int{from, to})
d.mergeRegions = append(d.mergeRegions, []int{from, to})
return
}

if fromIndex != -1 && toIndex == -1 {
a.mergeRegions[fromIndex] = append(a.mergeRegions[fromIndex], to)
d.mergeRegions[fromIndex] = append(d.mergeRegions[fromIndex], to)
return
}

if fromIndex == -1 && toIndex != -1 {
a.mergeRegions[toIndex] = append(a.mergeRegions[toIndex], from)
d.mergeRegions[toIndex] = append(d.mergeRegions[toIndex], from)
return
}

}

// function for merging detected regions
func (a *Analyzer) merge(detectedRegions SkinMapList, mergeRegions [][]int) {
func (d *Detector) merge(detectedRegions SkinMapList, mergeRegions [][]int) {
var newDetectedRegions SkinMapList

// merging detected regions
Expand All @@ -222,67 +222,67 @@ func (a *Analyzer) merge(detectedRegions SkinMapList, mergeRegions [][]int) {
}

// clean up
a.clearRegions(newDetectedRegions)
d.clearRegions(newDetectedRegions)
}

// clean up function
// only push regions which are bigger than a specific amount to the final resul
func (a *Analyzer) clearRegions(detectedRegions SkinMapList) {
func (d *Detector) clearRegions(detectedRegions SkinMapList) {
for _, region := range detectedRegions {
if len(region) > 30 {
a.SkinRegions = append(a.SkinRegions, region)
d.SkinRegions = append(d.SkinRegions, region)
}
}
}

func (a *Analyzer) analyzeRegions() bool {
skinRegionLength := len(a.SkinRegions)
func (d *Detector) analyzeRegions() bool {
skinRegionLength := len(d.SkinRegions)

// if there are less than 3 regions
if skinRegionLength < 3 {
a.message = fmt.Sprintf("Less than 3 skin regions (%v)", skinRegionLength)
a.result = false
return a.result
d.message = fmt.Sprintf("Less than 3 skin regions (%v)", skinRegionLength)
d.result = false
return d.result
}

// sort the skinRegions
sort.Sort(a.SkinRegions)
//sort.Reverse(a.SkinRegions)
sort.Sort(d.SkinRegions)
//sort.Reverse(d.SkinRegions)

// count total skin pixels
var totalSkin float64
for _, region := range a.SkinRegions {
for _, region := range d.SkinRegions {
totalSkin += float64(len(region))
}

// check if there are more than 15% skin pixel in the image
totalSkinParcentage := totalSkin / float64(a.totalPixels) * 100
totalSkinParcentage := totalSkin / float64(d.totalPixels) * 100
if totalSkinParcentage < 15 {
// if the parcentage lower than 15, it's not nude!
a.message = fmt.Sprintf("Total skin parcentage lower than 15 (%v%%)", totalSkinParcentage)
a.result = false
return a.result
d.message = fmt.Sprintf("Total skin parcentage lower than 15 (%v%%)", totalSkinParcentage)
d.result = false
return d.result
}

// check if the largest skin region is less than 35% of the total skin count
// AND if the second largest region is less than 30% of the total skin count
// AND if the third largest region is less than 30% of the total skin count
biggestRegionParcentage := float64(len(a.SkinRegions[0])) / totalSkin * 100
secondLargeRegionParcentage := float64(len(a.SkinRegions[1])) / totalSkin * 100
thirdLargesRegionParcentage := float64(len(a.SkinRegions[2])) / totalSkin * 100
biggestRegionParcentage := float64(len(d.SkinRegions[0])) / totalSkin * 100
secondLargeRegionParcentage := float64(len(d.SkinRegions[1])) / totalSkin * 100
thirdLargesRegionParcentage := float64(len(d.SkinRegions[2])) / totalSkin * 100
if biggestRegionParcentage < 35 &&
secondLargeRegionParcentage < 30 &&
thirdLargesRegionParcentage < 30 {
a.message = "Less than 35%, 30%, 30% skin in the biggest regions"
a.result = false
return a.result
d.message = "Less than 35%, 30%, 30% skin in the biggest regions"
d.result = false
return d.result
}

// check if the number of skin pixels in the largest region is less than 45% of the total skin count
if biggestRegionParcentage < 45 {
a.message = fmt.Sprintf("The biggest region contains less than 45%% (%v)", biggestRegionParcentage)
a.result = false
return a.result
d.message = fmt.Sprintf("The biggest region contains less than 45%% (%v)", biggestRegionParcentage)
d.result = false
return d.result
}

// TODO:
Expand All @@ -299,18 +299,18 @@ func (a *Analyzer) analyzeRegions() bool {
// if there are more than 60 skin regions and the average intensity within the polygon is less than 0.25
// the image is not nude
if skinRegionLength > 60 {
a.message = fmt.Sprintf("More than 60 skin regions (%v)", skinRegionLength)
a.result = false
return a.result
d.message = fmt.Sprintf("More than 60 skin regions (%v)", skinRegionLength)
d.result = false
return d.result
}

// otherwise it is nude
a.result = true
return a.result
d.result = true
return d.result
}

func (a *Analyzer) String() string {
return fmt.Sprintf("#<nude.Analyzer result=%t, message=%s>", a.result, a.message)
func (d *Detector) String() string {
return fmt.Sprintf("#<nude.Detector result=%t, message=%s>", d.result, d.message)
}

// A Survey on Pixel-Based Skin Color Detection Techniques
Expand Down

0 comments on commit 3452ee5

Please sign in to comment.