first commit

This commit is contained in:
编码猿
2024-09-27 01:20:28 +08:00
commit ddc91bf4e2
137 changed files with 4017 additions and 0 deletions

1
app/lib/face/.pydio Normal file
View File

@@ -0,0 +1 @@
af6921d2-187d-4cc8-b5eb-2db957efd2f6

125
app/lib/face/ImagePro.py Executable file
View File

@@ -0,0 +1,125 @@
import base64
import io
import os
from PIL import Image, ImageColor
class ImageProCls:
base64FilePath=None
@staticmethod
def humanbody_blending_with_image(input_image, gray_image, bg_image):
"""
:param input_image: the PIL.Image instance, the source humanbody image
:param gray_image: the PIL.Image instance, it is created from api base64 result, a gray image
:param bg_image: the PIL.Image instance, the background image you want to replace
:return: the PIL.Image instance is blending with humanbody
notes: you should close the return object after you leave
"""
input_width, input_height = input_image.size
bg_width, bg_height = bg_image.size
input_aspect_ratio = input_width / float(input_height)
bg_aspect_ratio = bg_width / float(bg_height)
if bg_aspect_ratio > input_aspect_ratio:
target_width, target_height = int(bg_height * input_aspect_ratio), bg_height
else:
target_width, target_height = bg_width, int(bg_width / input_aspect_ratio)
crop_image = bg_image.crop((0, 0, 0+target_width, 0+target_height))
new_image = crop_image.resize((input_width, input_height))
crop_image.close()
for x in range(0, input_width):
for y in range(0, input_height):
coord = (x, y)
gray_pixel_value = gray_image.getpixel(coord)
input_rgb_color = input_image.getpixel(coord)
bg_rgb_color = new_image.getpixel(coord)
confidence = gray_pixel_value / 255.0
alpha = confidence
R = input_rgb_color[0] * alpha + bg_rgb_color[0] * (1 - alpha)
G = input_rgb_color[1] * alpha + bg_rgb_color[1] * (1 - alpha)
B = input_rgb_color[2] * alpha + bg_rgb_color[2] * (1 - alpha)
R = max(0, min(int(R), 255))
G = max(0, min(int(G), 255))
B = max(0, min(int(B), 255))
new_image.putpixel(coord, (R, G, B))
return new_image
@staticmethod
def humanbody_blending_with_color(input_image, gray_image, bg_color):
"""
:param input_image: the PIL.Image instance
:param gray_image: the PIL.Image instance, it is created from api base64 result, it is a gray image
:param bg_color: a color string value, such as '#FFFFFF'
:return: PIL.Image instance
notes: you should close the return object after you leave
"""
input_width, input_height = input_image.size
bg_rgb_color = ImageColor.getrgb(bg_color)
new_image = Image.new("RGB", input_image.size, bg_color)
for x in range(0, input_width):
for y in range(0, input_height):
coord = (x, y)
gray_pixel_value = gray_image.getpixel(coord)
input_rgb_color = input_image.getpixel(coord)
confidence = gray_pixel_value / 255.0
alpha = confidence
R = input_rgb_color[0] * alpha + bg_rgb_color[0] * (1 - alpha)
G = input_rgb_color[1] * alpha + bg_rgb_color[1] * (1 - alpha)
B = input_rgb_color[2] * alpha + bg_rgb_color[2] * (1 - alpha)
R = max(0, min(int(R), 255))
G = max(0, min(int(G), 255))
B = max(0, min(int(B), 255))
new_image.putpixel(coord, (R, G, B))
return new_image
@staticmethod
def getSegmentImg(filePath):
input_file = ''
with open(filePath, 'r') as f:
input_file = f.read()
input_file = base64.b64decode(input_file)
gray_image = Image.open(io.BytesIO(input_file))
input_image = Image.open('./imgResource/segment.jpg', 'r')
new_image = ImageProCls.humanbody_blending_with_color(input_image, gray_image, '#FFFFFF')
new_image.save('./imgResource/resultImg.jpg')
print('-' * 60)
print('结果已经生成生成文件名resultImg.jpg请在imgResource/目录下查看')
if os.path.exists(filePath):
os.remove(filePath)
f.close()
new_image.close()
input_image.close()
gray_image.close()
@staticmethod
def getMergeImg(base64Str):
imgdata = base64.b64decode(base64Str)
file = open('./imgResource/MergeResultImg.jpg', 'wb')
file.write(imgdata)
file.close()
print('结果已经生成生成文件名MergeResultImg.jpg请在imgResource/目录下查看')

0
app/lib/face/__init__.py Executable file
View File

View File

@@ -0,0 +1 @@
2cd2cff3-ad8d-41e2-a0a8-ef9e540f2339

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

64
app/lib/face/compat.py Executable file
View File

@@ -0,0 +1,64 @@
# -*- coding: utf-8 -*-
"""
This module handles import compatibility issues between Python 2 and
Python 3.
"""
import sys
import random
import string
# -------
# Pythons
# -------
# Syntax sugar.
_ver = sys.version_info
#: Python 2.x?
is_py2 = (_ver[0] == 2)
#: Python 3.x?
is_py3 = (_ver[0] == 3)
try:
import simplejson as json
except ImportError:
import json
# ---------
# Specifics
# ---------
if is_py2:
from urllib2 import Request, urlopen, HTTPError, URLError
builtin_str = str
bytes = str
str = unicode
basestring = basestring
numeric_types = (int, long, float)
integer_types = (int, long)
elif is_py3:
from urllib.request import Request, urlopen
from urllib.error import HTTPError, URLError
builtin_str = str
str = str
bytes = bytes
basestring = (str, bytes)
numeric_types = (int, float)
integer_types = (int,)
def enc(x):
if isinstance(x, str):
return x.encode('utf-8')
elif isinstance(x, numeric_types):
return str(x).encode('utf-8')
return x
def choose_boundary():
rand_letters = ''.join(random.sample(string.ascii_letters+string.digits, 15))
return '{ch}{flag}{rand}'.format(ch='-'*6, flag='PylibFormBoundary', rand=rand_letters)

320
app/lib/face/facepp.py Executable file
View File

@@ -0,0 +1,320 @@
# -*- coding: utf-8 -*-
"""a simple facepp sdk
usage:
api = API(key, secret)
api.detect(img = File('/tmp/test.jpg'))
"""
import sys
import socket
import json
import os.path
import itertools
import mimetypes
import time
from collections.abc import Iterable
from app.lib.face.structures import ObjectDict
from app.lib.face.compat import (basestring, str, numeric_types, enc, choose_boundary,
Request, urlopen, HTTPError, URLError)
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
__all__ = ['File', 'APIError', 'API']
DEBUG_LEVEL = 1
# 添加API Key API Secret
API_KEY = "xfXREfL_pXgnqK2GedOunNPN2MFYSsPR"
API_SECRET = "x0PGyvHoVSjX19KlkjH1Ct7Md5wxz8aV"
class File(object):
"""an object representing a local file"""
path = None
content = None
def __init__(self, path):
self.path = path
self._get_content()
def _get_content(self):
"""read image content"""
if os.path.getsize(self.path) > 2 * 1024 * 1024:
raise APIError(-1, None, 'image file size too large')
else:
with open(self.path, 'rb') as f:
self.content = f.read()
def get_filename(self):
return os.path.basename(self.path)
class APIError(Exception):
code = None
"""HTTP status code"""
url = None
"""request URL"""
body = None
"""server response body; or detailed error information"""
def __init__(self, code, url, body):
self.code = code
self.url = url
self.body = body
def __str__(self):
return 'code={s.code}\nurl={s.url}\n{s.body}'.format(s=self)
__repr__ = __str__
class API(object):
key = None
secret = None
server = 'https://api-cn.faceplusplus.com'
decode_result = True
timeout = None
max_retries = None
retry_delay = None
def __init__(self):
"""
:param srv: The API server address
:param decode_result: whether to json_decode the result
:param timeout: HTTP request timeout in seconds
:param max_retries: maximal number of retries after catching URL error
or socket error
:param retry_delay: time to sleep before retrying
"""
if len(API_KEY)==0 or len(API_SECRET)==0:
print('\n'+'请在'+os.path.realpath(__file__)+'文件中填写正确的API_KEY和API_SECRET'+'\n')
exit(1)
self.key = API_KEY
self.secret = API_SECRET
srv = None
decode_result = True
timeout = 30
max_retries = 10
retry_delay = 5
if srv:
self.server = srv
self.decode_result = decode_result
assert timeout >= 0 or timeout is None
assert max_retries >= 0
self.timeout = timeout
self.max_retries = max_retries
self.retry_delay = retry_delay
_setup_apiobj(self, self, '', [])
def update_request(self, request):
"""overwrite this function to update the request before sending it to
server"""
pass
def _setup_apiobj(self, api, prefix, path):
if self is not api:
self._api = api
self._urlbase = '{server}/{prefix}/{path}'.format(server=api.server, prefix=prefix, path='/'.join(path))
lvl = len(path)
done = set()
for prefix, paths in _APIS:
for i in paths:
if len(i) <= lvl:
continue
cur = i[lvl]
if i[:lvl] == path and cur not in done:
done.add(cur)
setattr(self, cur, _APIProxy(api, prefix, i[:lvl + 1]))
class _APIProxy(object):
_api = None
"""underlying :class:`API` object"""
_urlbase = None
def __init__(self, api, prefix, path):
_setup_apiobj(self, api, prefix, path)
def __call__(self, *args, **kargs):
if len(args):
raise TypeError('Only keyword arguments are allowed')
form = _MultiPartForm()
for (k, v) in kargs.items():
if isinstance(v, File):
form.add_file(k, v.get_filename(), v.content)
url = self._urlbase
for k, v in self._mkarg(kargs).items():
form.add_field(k, v)
body = form.bytes
request = Request(url, data=body)
request.add_header('Content-type', form.get_content_type())
request.add_header('Content-length', str(len(body)))
self._api.update_request(request)
retry = self._api.max_retries
while True:
retry -= 1
try:
ret = urlopen(request, timeout=self._api.timeout).read()
break
except HTTPError as e:
raise APIError(e.code, url, e.read())
except (socket.error, URLError) as e:
if retry < 0:
raise e
_print_debug('caught error: {}; retrying'.format(e))
time.sleep(self._api.retry_delay)
if self._api.decode_result:
try:
ret = json.loads(ret, object_hook=ObjectDict)
except:
raise APIError(-1, url, 'json decode error, value={0!r}'.format(ret))
return ret
def _mkarg(self, kargs):
"""change the argument list (encode value, add api key/secret)
:return: the new argument list"""
kargs = kargs.copy()
kargs['api_key'] = self._api.key
kargs['api_secret'] = self._api.secret
for k, v in list(kargs.items()):
if isinstance(v, Iterable) and not isinstance(v, basestring):
kargs[k] = ','.join(v)
elif isinstance(v, File) or v is None:
del kargs[k]
elif isinstance(v, numeric_types):
kargs[k] = str(v)
else:
kargs[k] = v
return kargs
class _MultiPartForm(object):
"""Accumulate the data to be used when posting a form."""
def __init__(self):
self.form_fields = []
self.files = []
self.boundary = choose_boundary()
def get_content_type(self):
return 'multipart/form-data; boundary={}'.format(self.boundary)
def add_field(self, name, value):
"""Add a simple field to the form data."""
self.form_fields.append((name, value))
def add_file(self, fieldname, filename, content, mimetype=None):
"""Add a file to be uploaded."""
if mimetype is None:
mimetype = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
self.files.append((fieldname, filename, mimetype, content))
@property
def bytes(self):
"""Return a string(2.x) or bytes(3.x) representing the form data, including attached files."""
# Build a list of lists, each containing "lines" of the
# request. Each part is separated by a boundary string.
# Once the list is built, return a string where each
# line is separated by '\r\n'.
parts = []
part_boundary = "--" + self.boundary
# Add the form fields
parts.extend(
[part_boundary,
'Content-Disposition: form-data; name="{}"'.format(name), '', value]
for name, value in self.form_fields
)
# Add the files to upload
parts.extend(
[part_boundary,
'Content-Disposition: form-data; name="{}"; filename="{}"'.format(field_name, filename),
'Content-Type: {}'.format(content_type),
'',
body,
]
for field_name, filename, content_type, body in self.files
)
# Flatten the list and add closing boundary marker,
# then return CR+LF separated data
flattened = list(itertools.chain(*parts))
flattened.append(part_boundary + '--')
flattened.append('')
return b'\r\n'.join(enc(x) for x in flattened)
def _print_debug(msg):
if DEBUG_LEVEL:
sys.stderr.write(str(msg) + '\n')
_APIS = [
{
'prefix': 'facepp/v3',
'paths': [
'/detect',
'/compare',
'/search',
'/faceset/create',
'/faceset/addface',
'/faceset/removeface',
'/faceset/update',
'/faceset/getdetail',
'/faceset/delete',
'/faceset/getfacesets',
'/face/analyze',
'/face/getdetail',
'/face/setuserid',
],
},
{
'prefix': 'humanbodypp/v1',
'paths': [
'/detect',
'/segment',
]
},
{
'prefix': 'cardpp/v1',
'paths': [
'/ocridcard',
'/ocrdriverlicense',
'/ocrvehiclelicense',
'/ocrbankcard',
]
},
{
'prefix': 'imagepp/v1',
'paths': [
'/licenseplate',
'/recognizetext',
'/mergeface'
]
}
]
_APIS = [(i['prefix'], [p.split('/')[1:] for p in i['paths']]) for i in _APIS]

19
app/lib/face/structures.py Executable file
View File

@@ -0,0 +1,19 @@
class ObjectDict(dict):
"""Dictionary object for json decode"""
def __getattr__(self, name):
if name in self:
return self[name]
else:
raise AttributeError("No such attribute: " + name)
def __setattr__(self, name, value):
self[name] = value
def __delattr__(self, name):
if name in self:
del self[name]
else:
raise AttributeError("No such attribute: " + name)