feat: 目录层级变更
This commit is contained in:
@@ -45,7 +45,6 @@ const requestTimeout = 60 * time.Second
|
||||
// Detector 封装一个本地 python 服务的客户端。
|
||||
type Detector struct {
|
||||
url string
|
||||
threshold float64
|
||||
workers int
|
||||
client *http.Client
|
||||
cmd *exec.Cmd
|
||||
@@ -60,10 +59,7 @@ type Detector struct {
|
||||
}
|
||||
|
||||
// Start 拉起本地 python 检测服务并等它就绪。
|
||||
func Start(pythonPath string, threshold float64, workers int) (*Detector, error) {
|
||||
if threshold <= 0 || threshold >= 1 {
|
||||
threshold = 0.5
|
||||
}
|
||||
func Start(pythonPath string, workers int) (*Detector, error) {
|
||||
if workers <= 0 {
|
||||
workers = 2 // 默认 2 个 worker
|
||||
}
|
||||
@@ -88,7 +84,6 @@ func Start(pythonPath string, threshold float64, workers int) (*Detector, error)
|
||||
}
|
||||
|
||||
d := &Detector{
|
||||
threshold: threshold,
|
||||
workers: workers,
|
||||
client: &http.Client{Timeout: requestTimeout},
|
||||
python: py,
|
||||
@@ -189,33 +184,32 @@ type AnimeRatings struct {
|
||||
Explicit float64 `json:"explicit"`
|
||||
}
|
||||
|
||||
// Detect 检测一张动漫图片是否色情。返回:
|
||||
// Detect 检测一张动漫图片的色情评分。返回:
|
||||
// - score:max(explicit, questionable) 的 sigmoid 分数(若 G 最高则为 0)
|
||||
// - nsfw:是否判定为色情(分数 >= 阈值)
|
||||
// - ratings:四个 rating 的原始分数
|
||||
// - err:检测失败
|
||||
func (d *Detector) Detect(path string) (score float64, nsfw bool, ratings AnimeRatings, err error) {
|
||||
score, nsfw, ratings, err = d.detectOnce(path)
|
||||
func (d *Detector) Detect(path string) (score float64, ratings AnimeRatings, err error) {
|
||||
score, ratings, err = d.detectOnce(path)
|
||||
if err == nil {
|
||||
return score, nsfw, ratings, nil
|
||||
return score, ratings, nil
|
||||
}
|
||||
var ce *connError
|
||||
if !errors.As(err, &ce) {
|
||||
return score, nsfw, ratings, err
|
||||
return score, ratings, err
|
||||
}
|
||||
|
||||
d.restartMu.Lock()
|
||||
defer d.restartMu.Unlock()
|
||||
|
||||
if d.isStopped() {
|
||||
return 0, false, ratings, err
|
||||
return 0, ratings, err
|
||||
}
|
||||
if d.healthy() {
|
||||
return d.detectOnce(path)
|
||||
}
|
||||
fmt.Printf("=== 动漫检测服务失联(%v), 正在重启…\n", ce.err)
|
||||
if rerr := d.launch(); rerr != nil {
|
||||
return 0, false, ratings, fmt.Errorf("动漫检测服务重启失败: %v", rerr)
|
||||
return 0, ratings, fmt.Errorf("动漫检测服务重启失败: %v", rerr)
|
||||
}
|
||||
fmt.Println("=== 动漫检测服务已重启,继续识别")
|
||||
return d.detectOnce(path)
|
||||
@@ -242,24 +236,22 @@ func (d *Detector) isStopped() bool {
|
||||
return d.stopped
|
||||
}
|
||||
|
||||
func (d *Detector) detectOnce(path string) (score float64, nsfw bool, ratings AnimeRatings, err error) {
|
||||
func (d *Detector) detectOnce(path string) (score float64, ratings AnimeRatings, err error) {
|
||||
body, _ := json.Marshal(map[string]interface{}{
|
||||
"path": path,
|
||||
"threshold": d.threshold,
|
||||
"path": path,
|
||||
})
|
||||
resp, err := d.client.Post(d.url+"/detect", "application/json", bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return 0, false, ratings, &connError{err}
|
||||
return 0, ratings, &connError{err}
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return 0, false, ratings, err
|
||||
return 0, ratings, err
|
||||
}
|
||||
var out struct {
|
||||
Ok bool `json:"ok"`
|
||||
Error string `json:"error"`
|
||||
Nsfw bool `json:"nsfw"`
|
||||
Score float64 `json:"score"`
|
||||
Ratings struct {
|
||||
General float64 `json:"general"`
|
||||
@@ -270,10 +262,10 @@ func (d *Detector) detectOnce(path string) (score float64, nsfw bool, ratings An
|
||||
TopTags []map[string]interface{} `json:"top_tags"`
|
||||
}
|
||||
if err := json.Unmarshal(data, &out); err != nil {
|
||||
return 0, false, ratings, fmt.Errorf("解析检测结果失败: %v", err)
|
||||
return 0, ratings, fmt.Errorf("解析检测结果失败: %v", err)
|
||||
}
|
||||
if !out.Ok {
|
||||
return 0, false, ratings, fmt.Errorf("检测服务返回错误: %s", out.Error)
|
||||
return 0, ratings, fmt.Errorf("检测服务返回错误: %s", out.Error)
|
||||
}
|
||||
ratings = AnimeRatings{
|
||||
General: out.Ratings.General,
|
||||
@@ -284,7 +276,7 @@ func (d *Detector) detectOnce(path string) (score float64, nsfw bool, ratings An
|
||||
// 打印 rating 详情(调试用)
|
||||
fmt.Printf("=== AnimeNSFW 检测详情 %s: [G=%.3f S=%.3f Q=%.3f E=%.3f]\n",
|
||||
path, ratings.General, ratings.Sensitive, ratings.Questionable, ratings.Explicit)
|
||||
return out.Score, out.Nsfw, ratings, nil
|
||||
return out.Score, ratings, nil
|
||||
}
|
||||
|
||||
type connError struct{ err error }
|
||||
@@ -305,10 +297,6 @@ func (d *Detector) Stop() {
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Detector) Threshold() float64 {
|
||||
return d.threshold
|
||||
}
|
||||
|
||||
func resolvePython(configured string) string {
|
||||
candidates := []string{}
|
||||
if strings.TrimSpace(configured) != "" {
|
||||
|
||||
Reference in New Issue
Block a user