app.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. import os
  2. import tempfile
  3. import face_recognition
  4. import requests
  5. import logging
  6. import jieba.analyse
  7. from flask import Flask, request, jsonify, json
  8. def create_app():
  9. app = Flask(__name__)
  10. def init_app():
  11. known_faces_dir = "./known_faces"
  12. load_known_faces(known_faces_dir)
  13. init_app()
  14. @app.route('/')
  15. def index(): # put application's code here
  16. return 'OK'
  17. @app.route('/recognize/url', methods=['POST'])
  18. def recognize_url():
  19. if 'url' not in request.json:
  20. return jsonify({'error': 'No URL provided'}), 400
  21. url = request.json.get('url')
  22. if not url:
  23. return jsonify({'error': 'Invalid URL'}), 400
  24. try:
  25. # 从 URL 下载文件
  26. response = requests.get(url)
  27. if response.status_code != 200:
  28. return jsonify({'error': 'Failed to download image from URL'}), 400
  29. # 创建一个临时文件保存下载的文件
  30. temp_file = tempfile.NamedTemporaryFile(delete=False)
  31. temp_file.write(response.content)
  32. temp_file.close()
  33. find = find_faces_in_image(temp_file.name, url)
  34. os.remove(temp_file.name) # 删除临时文件
  35. results = return_json(find)
  36. return results
  37. except Exception as e:
  38. return jsonify({'error': str(e)}), 500
  39. @app.route('/recognize/file', methods=['POST'])
  40. def recognize_file():
  41. if 'file' not in request.files:
  42. return jsonify({'error': 'No file part'}), 400
  43. file = request.files['file']
  44. if file.filename == '':
  45. return jsonify({'error': 'No selected file'}), 400
  46. if file:
  47. # 创建一个临时文件保存上传的文件
  48. temp_file = tempfile.NamedTemporaryFile(delete=False)
  49. file.save(temp_file.name)
  50. find = find_faces_in_image(temp_file.name, file.filename)
  51. os.remove(temp_file.name) # 删除临时文件
  52. results = return_json(find)
  53. return results
  54. return jsonify({'error': 'An error occurred'}), 500
  55. @app.route('/title/split', methods=['POST'])
  56. def get_title_split():
  57. if 'title' not in request.json:
  58. return jsonify({'error': 'No title provided'}), 400
  59. title = request.json.get('title')
  60. if not title:
  61. return jsonify({'error': 'not title'}), 400
  62. return evaluate(title, 3)
  63. return app
  64. # 调用 setup_logging 函数创建并配置日志记录器
  65. def setup_logging():
  66. # 创建一个 Logger 对象
  67. logger = logging.getLogger('sensitive-face-recognizer_logger')
  68. # 设置日志级别,可根据需要调整为 DEBUG、INFO、WARNING、ERROR 或 CRITICAL
  69. logger.setLevel(logging.INFO)
  70. # 创建一个 Handler 对象,这里使用 StreamHandler 输出到控制台
  71. console_handler = logging.StreamHandler()
  72. # 创建一个文件处理器,输出到文件
  73. file_handler = logging.FileHandler('app.log')
  74. # 创建一个 Formatter 对象,设置日志格式
  75. formatter = logging.Formatter('%(levelname)s - %(message)s')
  76. console_handler.setFormatter(formatter)
  77. file_handler.setFormatter(formatter)
  78. # 将 Handler 添加到 Logger 中
  79. logger.addHandler(console_handler)
  80. logger.addHandler(file_handler)
  81. return logger
  82. logger = setup_logging()
  83. def return_json(find):
  84. result = {
  85. "code": 0,
  86. "msg": "success",
  87. "data": None, # 将 data 初始化为 None
  88. "success": True
  89. }
  90. if find:
  91. result["data"] = {"find_face_status": 1}
  92. else:
  93. result["data"] = {"find_face_status": 2}
  94. json_result = json.dumps(result)
  95. return json_result
  96. # 全局变量存储已知人脸编码和名称
  97. known_face_encodings = []
  98. known_face_names = []
  99. def load_known_faces(known_faces_dir):
  100. global known_face_encodings, known_face_names
  101. known_face_encodings = []
  102. known_face_names = []
  103. for filename in os.listdir(known_faces_dir):
  104. if filename.endswith(".jpg") or filename.endswith(".png"):
  105. image_path = os.path.join(known_faces_dir, filename)
  106. image = face_recognition.load_image_file(image_path)
  107. face_encoding = face_recognition.face_encodings(image)[0]
  108. known_face_encodings.append(face_encoding)
  109. known_face_names.append(os.path.splitext(filename)[0])
  110. def get_face_similarity(known_face_encoding, face_encoding):
  111. # 计算两张脸的面部编码之间的距离
  112. face_distances = face_recognition.face_distance([known_face_encoding], face_encoding)
  113. # 计算相似度,使用 1 - 距离作为相似度
  114. similarity = 1 - face_distances
  115. return similarity
  116. def find_faces_in_image(image_path, url):
  117. image = face_recognition.load_image_file(image_path)
  118. face_locations = face_recognition.face_locations(image)
  119. face_encodings = face_recognition.face_encodings(image, face_locations)
  120. found_faces = []
  121. for face_encoding in face_encodings:
  122. matches = face_recognition.compare_faces(known_face_encodings, face_encoding, tolerance=0.35)
  123. if True in matches:
  124. first_match_index = matches.index(True)
  125. name = known_face_names[first_match_index]
  126. found_faces.append(name)
  127. known_face_encoding = known_face_encodings[first_match_index]
  128. similarity = get_face_similarity(known_face_encoding, face_encoding)
  129. logger.info(f'image_name={name} similarity={similarity} url={url}')
  130. if found_faces:
  131. return True
  132. else:
  133. return False
  134. def load_top_tags():
  135. kv = {}
  136. try:
  137. with open('top_tags.txt', 'r', encoding='utf-8') as cache_file:
  138. for index, line in enumerate(cache_file):
  139. if index == 10000:
  140. break
  141. line = line.strip()
  142. if not line:
  143. continue
  144. k, _ = line.split('\t')
  145. kv[k] = index
  146. except FileNotFoundError:
  147. print("未找到 top_tags.txt 文件。")
  148. return kv
  149. kv = load_top_tags()
  150. def evaluate(title, top_size):
  151. if title is None or len(title) == 0:
  152. return ""
  153. keys = jieba.analyse.extract_tags(title, topK=top_size, withWeight=False, allowPOS=('n', 'v'))
  154. if keys is None or len(keys) == 0:
  155. return ""
  156. keys_filter = []
  157. for k in keys:
  158. if k in kv:
  159. keys_filter.append(k)
  160. if len(keys_filter) == 0:
  161. return ""
  162. return ",".join(keys_filter)
  163. if __name__ == '__main__':
  164. app = create_app()
  165. app.run(host='0.0.0.0', port=5000)