Python automatically recognizes the yellow image

Source: Internet
Author: User
Tags diff unique id


From watchdog.observers import Observer
From watchdog.events Import *
Import time
Import Sys
Import OS
Import _io
From collections Import Namedtuple
From PIL import Image
Import Argparse

Class Nude (object):

Skin = Namedtuple ("Skin", "id skin region x y")

def __init__ (self, path_or_image):
# If the path_or_image is an instance of the Image.image type, assign the value directly
If Isinstance (Path_or_image, image.image):
Self.image = Path_or_image
# If Path_or_image is an instance of STR type, open the picture
Elif isinstance (Path_or_image, str):
Self.image = Image.open (path_or_image)

# Get pictures of all color channels
Bands = Self.image.getbands ()
# to determine whether a single-channel picture (also known as a grayscale), is to convert the grayscale image to an RGB graph
If Len (bands) = = 1:
# Create a new RGB image of the same size
new_img = Image.new ("RGB", Self.image.size)
# Copy Grayscale image self.image to RGB figure New_img.paste (PIL automatically color channel conversion)
New_img.paste (Self.image)
f = self.image.filename
# Replace Self.image
Self.image = new_img
Self.image.filename = f

# Store all Skin objects for all pixels in the image
Self.skin_map = []
# The skin area is detected, the index of the element is the skin area number, and the element is a list containing some skin objects
Self.detected_regions = []
# elements are lists that contain some int objects (area numbers)
# The regions in these elements represent areas that are to be merged
Self.merge_regions = []
# The integrated skin area, the index of the element is the skin area number, the element is a list containing some skin objects
Self.skin_regions = []
# The region number of the recently merged two skin regions, initialized to-1
Self.last_from, self.last_to =-1,-1
# Erotic Image Judging Results
Self.result = None
# Process the information you get
Self.message = None
# Image Width High
Self.width, self.height = self.image.size
# Total Image pixels
Self.total_pixels = Self.width * self.height

def resize (self, maxwidth=1000, maxheight=1000):
"""
Resize the picture proportionally based on the maximum width and height,
Note: This may affect the results of the detection algorithm

Returns 0 if there is no change
Original width greater than maxwidth return 1
Original height greater than maxheight return 2
The original width height is greater than MaxWidth, MaxHeight returns 3

MaxWidth-Maximum picture width
MaxHeight-picture max height
can be set to False to ignore
"" "
# Store return value
Ret = 0
If MAXWIDTH:
if self.width > maxwidth:
wpercent = (maxwidth/self.width)
hsize = Int ((self.height * wpercent))
FName = Self.image.filename
# Image.lanczos is a resampling filter for antialiasing
Self.image = Self.image.resize ((maxwidth, hsize), Image.lanczos)
Self.image.filename = fname
Self.width, self.height = self.image.size
Self.total_pixels = Self.width * Self.height
ret + = 1
If maxheight:
If Self.height > maxheight:
hpercent = (Maxheight/flo at (self.height))
wsize = Int ((float (self.width) * FLOAT (hpercent)))
FName = self.image.filename
Self.image = Self.image.resize ((wsize, maxheight), image.lanczos)
Self.image.filename = fname
Self.width, self.height = Self.image.size
Self.total_pixels = self.width * Self.height
ret + = 2
return ret

# analysis function
Def parse (self):
# If there is a result, return this object
If Self.result is not None:
return self
# Get image all pixel data
pixels = Self.image.load ()
# Traverse each pixel
For y in range (self.height):
For x in range (self.width):
# Gets the RGB three-channel value of the pixel
# [x, Y] is an easy way to do [(y)]
r = pixels[x, Y][0] # red
g = Pixels[x, y][1] # Green
b = Pixels[x, y][2] # Blue
# Determine if the current pixel is a skin color pixel
Isskin = True If Self._classify_skin (R, G, b) Else False
# Assign a unique ID value to each pixel (1, 2, 3...height*width)
# Note X, Y's value starts from zero
_id = x + y * self.width + 1
# Create a corresponding Skin object for each pixel and add it to the Self.skin_map
Self.skin_map.append (self. Skin (_id, Isskin, None, X, y))
# skip This loop if the current pixel is not a skin-color pixel
If not Isskin:
Continue

# set the upper left corner as the origin, the neighboring pixels are the symbol *, the current pixel is the symbol ^, then the relationship between the positions is usually
# ***
# *^

# There is a list of adjacent pixel indexes, which are stored in order from large to small, and the order changes have influence
# Note that _id is starting at 1, and the corresponding index is _id-1
Check_indexes = [_id-2, # pixels to the left of the current pixel
_id-self.width-2, # pixels at the top left of the current pixel
_id-self.width-1, # pixels above the current pixel
_id-self.width] # pixels at the top right of the current pixel
# used to record the area number of the skin color pixels in the neighboring pixel, initialized to-1
Region =-1
# Iterate through the index of each neighboring pixel
For index in check_indexes:
# try to index the Skin object of neighboring pixels, no then jump out of the loop
Try
Self.skin_map[index]
Except Indexerror:
Break
# Neighboring pixels are skin-color pixels:
If Self.skin_map[index].skin:
# If the neighboring pixel and region of the current pixel are valid values, and they are different, and the same merge task has not been added
if (self.skin_map[index].region! = None and
Region! = None and Region! =-1 and
Self.skin_map[index].region! = region and
Self.last_from! = region and
Self.last_to! = self.skin_map[index].region):
# So this adds merge tasks for both regions
Self._add_merge (region, Self.skin_map[index].region)
# Record the region number of this neighboring pixel
Region = Self.skin_map[index].region
# after traversing all neighboring pixels, if region is still equal to-1, it means that all neighboring pixels are not skin-color pixels
If region = =-1:
# Change the property to the new zone number, note that the tuple is immutable and cannot be changed directly
_skin = Self.skin_map[_id-1]._replace (Region=len (self.detected_regions))
SELF.SKIN_MAP[_ID-1] = _skin
# Create this skin color pixel area as a new region
Self.detected_regions.append ([self.skin_map[_id-1]])
# Region is not equal to 1 and not equal to none, indicating that there is an area number as a valid value for the neighboring skin pixels
Elif Region! = None:
# Change the region number of this pixel to be the same as neighboring pixels
_skin = Self.skin_map[_id-1]._replace (region=region)
SELF.SKIN_MAP[_ID-1] = _skin
# Add this pixel to the list of pixels in this region
Self.detected_regions[region].append (Self.skin_map[_id-1])
# Complete All Area merge tasks, merge the sorted areas into self.skin_regions
Self._merge (Self.detected_regions, self.merge_regions)
# Analyze skin area to get judgment result
Self._analyse_regions ()
return self


# The elements of self.merge_regions are lists that contain some int objects (area numbers)
# The area represented by the Self.merge_regions element is the area to be merged
# This method adds two regions to be merged into the Self.merge_regions
def _add_merge (self, _from, _to):
# Two zone numbers assigned to class properties
Self.last_from = _from
Self.last_to = _to

# record an index value of self.merge_regions, initialized to-1
From_index =-1
# record an index value of self.merge_regions, initialized to-1
To_index =-1


# Iterate through the elements of each self.merge_regions
For index, region in enumerate (self.merge_regions):
# iterate through each area number in the element
For R_index Inch:
if R_index = = _from:
From_index = Index
if R_index = = _to:
To_index = Index

# If two region numbers are present in self.merge_regions
If From_index! =-1 and To_index! =-1:
# If these two zones exist in two lists, respectively
# then merge the two lists
If From_index! = To_index:
Self.merge_regions[from_index].extend (Self.merge_regions[to_index])
Del (Self.merge_regions[to_index])
Return

# If two zone numbers are not present in self.merge_regions
if From_index = =-1 and To_index = =-1:
# Create a new zone number list
Self.merge_regions.append ([_from, _to])
Return
# If one of the two region numbers is present in self.merge_regions
If From_index! =-1 and To_index = =-1:
# will not exist in the Self.merge_regions area number
# Add to the list where another zone number is located
Self.merge_regions[from_index].append (_to)
Return
# If one of the two area numbers to be merged exists in Self.merge_regions
if From_index = =-1 and To_index! =-1:
# will not exist in the Self.merge_regions area number
# Add to the list where another zone number is located
Self.merge_regions[to_index].append (_from)
Return

# Merge the skin area of the merge
def _merge (self, detected_regions, merge_regions):
# New List New_detected_regions
# its elements will be a list of Skin objects that contain some pixels
# The elements of New_detected_regions represent the skin area, and the element index is the area number
New_detected_regions = []

# Merges all regions represented by the region number in the element in Merge_regions
For index, region in enumerate (merge_regions):
Try
New_detected_regions[index]
Except Indexerror:
New_detected_regions.append ([])
For R_index Inch:
New_detected_regions[index].extend (Detected_regions[r_index])
Detected_regions[r_index] = []

# Add the rest of the remaining skin areas to the new_detected_regions
For region in Detected_regions:
If Len (region) > 0:
New_detected_regions.append (region)

# Clean New_detected_regions
Self._clear_regions (new_detected_regions)

# Skin Area cleanup function
# save only a few pixels greater than the specified number of skin areas
def _clear_regions (self, detected_regions):
For region in Detected_regions:
If Len (region) > 30:
Self.skin_regions.append (region)

# Analysis Area
def _analyse_regions (self):
# If the skin area is less than 3, not a pornographic
# If Len (self.skin_regions) < 3:
# self.message = "Less than 2 skins regions ({_skin_regions_size})". Format (
# _skin_regions_size=len (self.skin_regions))
# Self.result = False
# return Self.result

# Sort the Skin area
Self.skin_regions = sorted (self.skin_regions, Key=lambda S:len (s),
Reverse=true)

# Calculate total number of skin pixels
Total_skin = float (SUM ([Len (skin_region) for skin_region in Self.skin_regions])

# If the ratio of the skin area to the entire image is less than 15%, then not pornographic pictures
If Total_skin/self.total_pixels * < 15:
Self.message = "Total skin percentage lower than ({:. 2f})". Format (total_skin/self.total_pixels * 100)
Self.result = False
Return Self.result

# If the maximum skin area is less than 45% of total skin area, not pornographic pictures
If Len (Self.skin_regions[0])/Total_skin * < 45:
Self.message = "The biggest region contains less than ({:. 2f})". Format (len (self.skin_regions[0])/total_skin * 100)
Self.result = False
Return Self.result

# More than 60 skin areas, not pornographic images
If Len (self.skin_regions) > 60:
Self.message = "More than skin regions ({})". Format (len (self.skin_regions))
Self.result = False
Return Self.result

# Other situations for erotic pictures
Self.message = "nude!!"
Self.result = True
Return Self.result

# pixel-based skin tone detection technology
def _classify_skin (self, r, G, b):
# Judging by RGB values
Rgb_classifier = r >
G > G < and \
b > and \
Max ([R, G, b])-min ([R, G, b]) >
ABS (R-G) >
R > G and \
R > B
# based on the processed RGB value determination
NR, ng, NB = self._to_normalized (R, G, b)
Norm_rgb_classifier = nr/ng > 1.185 and \
Float (R * b)/((R + G + B) * * 2) > 0.107 and \
Float (R * g)/((R + G + B) * * 2) > 0.112

# Judging in HSV color mode
H, s, v = SELF._TO_HSV (R, G, b)
Hsv_classifier = h > 0 and \
H < and \
s > 0.23 and \
s < 0.68

# YCbCr in color mode
Y, cb, CR = SELF._TO_YCBCR (R, G, b)
Ycbcr_classifier = 97.5 <= cb <= 142.5 and 134 <= CR <= 176

# The effect is not very good, also need to change the formula
# return Rgb_classifier or Norm_rgb_classifier or Hsv_classifier or ycbcr_classifier
Return Ycbcr_classifier

def _to_normalized (self, r, G, b):
If r = = 0:
r = 0.0001
If G = = 0:
g = 0.0001
If b = = 0:
b = 0.0001
_sum = Float (r + G + B)
return [R/_sum, G/_sum, b/_sum]

def _to_ycbcr (self, r, G, b):
# Source of the formula:
# Http://stackoverflow.com/questions/19459831/rgb-to-ycbcr-conversion-problems
y =. 299*r +. 587*g +. 114*b
CB = 128-0.168736*r-0.331364*g + 0.5*b
CR = + 0.5*r-0.418688*g-0.081312*b
Return y, CB, CR

def _TO_HSV (self, r, G, b):
H = 0
_sum = Float (r + G + B)
_max = float (max ([R, G, b]))
_min = float (min ([R, G, b]))
diff = Float (_max-_min)
If _sum = = 0:
_sum = 0.0001

If _max = = r:
if diff = = 0:
H = sys.maxsize
Else
h = (g-b)/diff
elif _max = = G:
H = 2 + ((g-r)/diff)
Else
H = 4 + ((r-g)/diff)

H *= 60
If h < 0:
H + = 360

return [H, 1.0-(3.0 * (_min/_sum)), (1.0/3.0) * _max]

def inspect (self):
_image = ' {} {} {}x{} '. Format (Self.image.filename, Self.image.format, Self.width, Self.height)
Return "{_image}: Result={_result} message= ' {_message} '". Format (_image=_image, _result=self.result, _message= Self.message)

# A picture file will be generated in the source file directory to visualize the skin area
def showskinregions (self):
# method returns when no results are obtained
If Self.result is None:
Return
# A collection of skin pixel IDs
Skinidset = set ()
# Make a copy of the original
Simage = Self.image
# Loading Data
Simagedata = Simage.load ()

# Put the ID of the skin pixel into skinidset
For SR in Self.skin_regions:
For Pixel in SR:
Skinidset.add (pixel.id)
# Set the skin pixels in the image to white and the rest to black
For Pixel in Self.skin_map:
If Pixel.id not in Skinidset:
Simagedata[pixel.x, Pixel.y] = 0, 0, 0
Else
Simagedata[pixel.x, pixel.y] = 255, 255, 255
# source File Absolute Path
FilePath = Os.path.abspath (self.image.filename)
# directory where source files are located
FileDirectory = Os.path.dirname (filePath) + '/'
# The full filename of the source file
Filefullname = Os.path.basename (FilePath)
# separate the full file name of the source file to get the file name and extension
FileName, Fileextname = Os.path.splitext (filefullname)
# Save Picture
Simage.save (' {}{}_{}{} '. Format (filedirectory, FileName, ' Nude ' if self.result Else ' Normal ', fileextname))

def del_files (path):
For root, dirs, files in Os.walk (path):
For name in Files:
If Name.endswith (". CR2 "):
Os.remove (Os.path.join (root, name))
Print ("Delete File:" + os.path.join (root, name))

Class Fileeventhandler (FileSystemEventHandler):
def __init__ (self):
Filesystemeventhandler.__init__ (self)


def on_created (self, event):
If Event.is_directory:
Pass
Else
Time.sleep (0.1)
fname = "{0}". Format (Event.src_path)
#fname = "D:/test/new/c.jpg"
If Os.path.isfile (fname):
n = Nude (fname)
N.resize (maxheight=800, maxwidth=600)
N.parse ()
Print (N.result, N.inspect ())
if (N.result):
Print (' true ')
My_file = fname
If Os.path.exists (my_file):
#删除文件
Os.remove (My_file)
Else
Print ("false")
Else
Print (fname, "is not a file")


if __name__ = = "__main__":
Observer = Observer ()
Event_handler = Fileeventhandler ()
Observer.schedule (Event_handler, ' d:\\test ', True)
Observer.start ()
Try
While True:
Time.sleep (1)
Except Keyboardinterrupt:
Observer.stop ()
Observer.join ()

Python automatically recognizes the yellow image

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.