🐳 add docker file

This commit is contained in:
2025-01-23 15:24:59 +08:00
parent c6af9a0461
commit fc95d73adb
27 changed files with 5117 additions and 269 deletions

155
.idea/GOHCache.xml generated
View File

@@ -122,6 +122,27 @@
</set>
</value>
</entry>
<entry key="CaffeClassificationLogic">
<value>
<set>
<option value="file://$PROJECT_DIR$/app/aisvc/rpc/internal/logic/aiservice/caffe_classification_logic.go" />
</set>
</value>
</entry>
<entry key="CaffeClassificationRequest">
<value>
<set>
<option value="file://$PROJECT_DIR$/app/aisvc/rpc/pb/aisvc.pb.go" />
</set>
</value>
</entry>
<entry key="CaffeClassificationResponse">
<value>
<set>
<option value="file://$PROJECT_DIR$/app/aisvc/rpc/pb/aisvc.pb.go" />
</set>
</value>
</entry>
<entry key="CasbinVerifyMiddleware">
<value>
<set>
@@ -267,7 +288,6 @@
<value>
<set>
<option value="file://$PROJECT_DIR$/app/aisvc/rpc/internal/logic/aiservice/face_recognition_logic.go" />
<option value="file://$PROJECT_DIR$/app/aisvc/rpc/internal/logic/facerecognitionservice/face_recognition_logic.go" />
</set>
</value>
</entry>
@@ -953,6 +973,27 @@
</set>
</value>
</entry>
<entry key="TfClassificationLogic">
<value>
<set>
<option value="file://$PROJECT_DIR$/app/aisvc/rpc/internal/logic/aiservice/tf_classification_logic.go" />
</set>
</value>
</entry>
<entry key="TfClassificationRequest">
<value>
<set>
<option value="file://$PROJECT_DIR$/app/aisvc/rpc/pb/aisvc.pb.go" />
</set>
</value>
</entry>
<entry key="TfClassificationResponse">
<value>
<set>
<option value="file://$PROJECT_DIR$/app/aisvc/rpc/pb/aisvc.pb.go" />
</set>
</value>
</entry>
<entry key="Token">
<value>
<set>
@@ -1325,7 +1366,7 @@
<entry key="file://D:/GoPath/pkg/mod/github.com/!kagami/go-face@v0.0.0-20210630145111-0c14797b4d0e/face.go">
<value>
<ScannedPath>
<option name="lastModified" value="1737436748224" />
<option name="lastModified" value="1737559935226" />
<option name="schema">
<list>
<option value="Recognizer" />
@@ -1335,13 +1376,6 @@
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/ai/rpc/generate.go">
<value>
<ScannedPath>
<option name="lastModified" value="1737425967125" />
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/aisvc/model/mysql/generate/generate.go">
<value>
<ScannedPath>
@@ -1402,10 +1436,17 @@
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/aisvc/rpc/build.go">
<value>
<ScannedPath>
<option name="lastModified" value="1737540237579" />
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/aisvc/rpc/client/aiservice/ai_service.go">
<value>
<ScannedPath>
<option name="lastModified" value="1737471643677" />
<option name="lastModified" value="1737535196216" />
<option name="schema">
<list>
<option value="defaultAiService" />
@@ -1417,7 +1458,7 @@
<entry key="file://$PROJECT_DIR$/app/aisvc/rpc/generate.go">
<value>
<ScannedPath>
<option name="lastModified" value="1737426199266" />
<option name="lastModified" value="1737540206762" />
</ScannedPath>
</value>
</entry>
@@ -1433,10 +1474,22 @@
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/aisvc/rpc/internal/logic/aiservice/caffe_classification_logic.go">
<value>
<ScannedPath>
<option name="lastModified" value="1737535196207" />
<option name="schema">
<list>
<option value="CaffeClassificationLogic" />
</list>
</option>
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/aisvc/rpc/internal/logic/aiservice/face_recognition_logic.go">
<value>
<ScannedPath>
<option name="lastModified" value="1737511014685" />
<option name="lastModified" value="1737604866085" />
<option name="schema">
<list>
<option value="FaceRecognitionLogic" />
@@ -1445,13 +1498,13 @@
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/app/aisvc/rpc/internal/logic/facerecognitionservice/face_recognition_logic.go">
<entry key="file://$PROJECT_DIR$/app/aisvc/rpc/internal/logic/aiservice/tf_classification_logic.go">
<value>
<ScannedPath>
<option name="lastModified" value="1737426415089" />
<option name="lastModified" value="1737534650883" />
<option name="schema">
<list>
<option value="FaceRecognitionLogic" />
<option value="TfClassificationLogic" />
</list>
</option>
</ScannedPath>
@@ -1460,7 +1513,7 @@
<entry key="file://$PROJECT_DIR$/app/aisvc/rpc/internal/server/aiservice/ai_service_server.go">
<value>
<ScannedPath>
<option name="lastModified" value="1737471643672" />
<option name="lastModified" value="1737535196211" />
<option name="schema">
<list>
<option value="AiServiceServer" />
@@ -1472,7 +1525,7 @@
<entry key="file://$PROJECT_DIR$/app/aisvc/rpc/internal/svc/service_context.go">
<value>
<ScannedPath>
<option name="lastModified" value="1737451498188" />
<option name="lastModified" value="1737534763350" />
<option name="schema">
<list>
<option value="ServiceContext" />
@@ -1484,11 +1537,15 @@
<entry key="file://$PROJECT_DIR$/app/aisvc/rpc/pb/aisvc.pb.go">
<value>
<ScannedPath>
<option name="lastModified" value="1737471643651" />
<option name="lastModified" value="1737535196194" />
<option name="schema">
<list>
<option value="FaceRecognitionRequest" />
<option value="FaceRecognitionResponse" />
<option value="TfClassificationRequest" />
<option value="TfClassificationResponse" />
<option value="CaffeClassificationRequest" />
<option value="CaffeClassificationResponse" />
<option value="x" />
</list>
</option>
@@ -1498,7 +1555,7 @@
<entry key="file://$PROJECT_DIR$/app/aisvc/rpc/pb/aisvc_grpc.pb.go">
<value>
<ScannedPath>
<option name="lastModified" value="1737471643657" />
<option name="lastModified" value="1737535196195" />
<option name="schema">
<list>
<option value="aiServiceClient" />
@@ -1511,7 +1568,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/api/auth.go">
<value>
<ScannedPath>
<option name="lastModified" value="1735112913996" />
<option name="lastModified" value="1737600178055" />
</ScannedPath>
</value>
</entry>
@@ -1677,7 +1734,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/api/internal/handler/routes.go">
<value>
<ScannedPath>
<option name="lastModified" value="1737092120580" />
<option name="lastModified" value="1737533432274" />
</ScannedPath>
</value>
</entry>
@@ -2060,7 +2117,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/api/internal/logic/storage/upload_file_logic.go">
<value>
<ScannedPath>
<option name="lastModified" value="1737478365272" />
<option name="lastModified" value="1737533110977" />
<option name="schema">
<list>
<option value="UploadFileLogic" />
@@ -2293,7 +2350,7 @@
<entry key="file://$PROJECT_DIR$/app/auth/api/internal/types/types.go">
<value>
<ScannedPath>
<option name="lastModified" value="1737092120578" />
<option name="lastModified" value="1737533432269" />
<option name="schema">
<list>
<option value="AccountLoginRequest" />
@@ -2767,6 +2824,20 @@
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/build.go">
<value>
<ScannedPath>
<option name="lastModified" value="1737603279477" />
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/common/caffe_classifier/caffe_classifier.go">
<value>
<ScannedPath>
<option name="lastModified" value="1737535248279" />
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/common/captcha/generate/generate_basic_text_captcha.go">
<value>
<ScannedPath>
@@ -2861,7 +2932,7 @@
<entry key="file://$PROJECT_DIR$/common/casbinx/casbin.go">
<value>
<ScannedPath>
<option name="lastModified" value="1735029589299" />
<option name="lastModified" value="1737600200600" />
</ScannedPath>
</value>
</entry>
@@ -2961,13 +3032,6 @@
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/common/face_recognition/face_recognition.go">
<value>
<ScannedPath>
<option name="lastModified" value="1737432158291" />
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/common/face_recognizer/face_recognizer.go">
<value>
<ScannedPath>
@@ -2975,13 +3039,6 @@
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/common/face_recognizer/face_recognizer_test.go">
<value>
<ScannedPath>
<option name="lastModified" value="1737464721501" />
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/common/gao_map/amap.go">
<value>
<ScannedPath>
@@ -3399,6 +3456,13 @@
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/common/tf_classifier/tf_classifier.go">
<value>
<ScannedPath>
<option name="lastModified" value="1737518434331" />
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/common/utils/encrypt.go">
<value>
<ScannedPath>
@@ -3425,13 +3489,6 @@
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/common/utils/generate_file_hash.go">
<value>
<ScannedPath>
<option name="lastModified" value="1736849903553" />
</ScannedPath>
</value>
</entry>
<entry key="file://$PROJECT_DIR$/common/utils/generate_image_hash.go">
<value>
<ScannedPath>
@@ -3531,6 +3588,9 @@
<entry key="bucket_properties" value="BucketProperties" />
<entry key="bucket_stat" value="BucketStat" />
<entry key="cache_entry" value="CacheEntry" />
<entry key="caffe_classification_logic" value="CaffeClassificationLogic" />
<entry key="caffe_classification_request" value="CaffeClassificationRequest" />
<entry key="caffe_classification_response" value="CaffeClassificationResponse" />
<entry key="casbin_verify_middleware" value="CasbinVerifyMiddleware" />
<entry key="code_msg" value="CodeMsg" />
<entry key="comment_content" value="CommentContent" />
@@ -3669,6 +3729,9 @@
<entry key="submit_reply_comment_logic" value="SubmitReplyCommentLogic" />
<entry key="submit_reply_reply_logic" value="SubmitReplyReplyLogic" />
<entry key="tencent_cos" value="TencentCOS" />
<entry key="tf_classification_logic" value="TfClassificationLogic" />
<entry key="tf_classification_request" value="TfClassificationRequest" />
<entry key="tf_classification_response" value="TfClassificationResponse" />
<entry key="token" value="Token" />
<entry key="unimplemented_ai_service_server" value="UnimplementedAiServiceServer" />
<entry key="upload_file_logic" value="UploadFileLogic" />
@@ -3684,6 +3747,6 @@
<entry key="x" value="x" />
</map>
</option>
<option name="lastTimeChecked" value="1737424561706" />
<option name="lastTimeChecked" value="1737523965355" />
</component>
</project>

125
aisvc.Dockerfile Normal file
View File

@@ -0,0 +1,125 @@
# to build this docker image:
# docker build --build-arg OPENCV_VERSION="4.11.0" -f aisvc.Dockerfile -t schisandra-ai-server .
# docker build --build-arg OPENCV_VERSION="4.x" --build-arg OPENCV_FILE="https://github.com/opencv/opencv/archive/refs/heads/4.x.zip" --build-arg OPENCV_CONTRIB_FILE="https://github.com/opencv/opencv_contrib/archive/refs/heads/4.x.zip" -f opencv.Dockerfile -t schisandra-cloud-album-server .
FROM golang:1.23.5-bullseye AS builder
LABEL maintainer="landaiqing <<landaiqing@126.com>>"
ENV TZ=Asia/Shanghai \
DEBIAN_FRONTEND=noninteractive
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN sed -i 's|http://deb.debian.org/debian|https://mirrors.tuna.tsinghua.edu.cn/debian|g' /etc/apt/sources.list && \
apt-get update && apt-get install -y --no-install-recommends --fix-missing \
tzdata git build-essential cmake pkg-config wget unzip libgtk2.0-dev \
curl ca-certificates libcurl4-openssl-dev libssl-dev \
libavcodec-dev libavformat-dev libswscale-dev libtbb2 libtbb-dev \
libharfbuzz-dev libfreetype6-dev \
libjpeg-dev libturbojpeg-dev libpng-dev libtiff-dev libdc1394-22-dev nasm \
libdlib-dev libblas-dev libatlas-base-dev liblapack-dev \
gcc g++ musl-dev cmake && \
rm -rf /var/lib/apt/lists/*
ARG OPENCV_VERSION="4.11.0"
ENV OPENCV_VERSION=$OPENCV_VERSION
ARG OPENCV_FILE="https://github.com/opencv/opencv/archive/${OPENCV_VERSION}.zip"
ENV OPENCV_FILE=$OPENCV_FILE
ARG OPENCV_CONTRIB_FILE="https://github.com/opencv/opencv_contrib/archive/${OPENCV_VERSION}.zip"
ENV OPENCV_CONTRIB_FILE=$OPENCV_CONTRIB_FILE
RUN curl -Lo opencv.zip ${OPENCV_FILE} && \
unzip -q opencv.zip && \
curl -Lo opencv_contrib.zip ${OPENCV_CONTRIB_FILE} && \
unzip -q opencv_contrib.zip && \
rm opencv.zip opencv_contrib.zip && \
cd opencv-${OPENCV_VERSION} && \
mkdir build && cd build && \
cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D WITH_IPP=OFF \
-D WITH_OPENGL=OFF \
-D WITH_QT=OFF \
-D WITH_FREETYPE=ON \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib-${OPENCV_VERSION}/modules \
-D OPENCV_ENABLE_NONFREE=ON \
-D WITH_JASPER=OFF \
-D WITH_TBB=ON \
-D BUILD_JPEG=ON \
-D WITH_SIMD=ON \
-D ENABLE_LIBJPEG_TURBO_SIMD=ON \
-D BUILD_DOCS=OFF \
-D BUILD_EXAMPLES=OFF \
-D BUILD_TESTS=OFF \
-D BUILD_PERF_TESTS=ON \
-D BUILD_opencv_java=NO \
-D BUILD_opencv_python=NO \
-D BUILD_opencv_python2=NO \
-D BUILD_opencv_python3=NO \
-D OPENCV_GENERATE_PKGCONFIG=ON .. && \
make -j $(nproc --all) && \
make preinstall && make install && ldconfig && \
cd / && rm -rf opencv*
WORKDIR /app
COPY . .
#WORKDIR /app/app/aisvc/
ENV CGO_ENABLED=1 \
CGO_CFLAGS="-I/usr/local/include/opencv4" \
CGO_CPPFLAGS="-I/usr/local/include" \
CGO_LDFLAGS="-L/usr/local/lib -lopencv_core -lopencv_face -lopencv_videoio -lopencv_imgproc -lopencv_highgui -lopencv_imgcodecs -lopencv_objdetect -lopencv_features2d -lopencv_video -lopencv_dnn -lopencv_xfeatures2d" \
GOOS=linux \
GOARCH=amd64 \
GOPROXY=https://goproxy.cn,direct
RUN go mod download
RUN go build -ldflags="-w -s" -o schisandra-ai-server ./app/aisvc/rpc/aisvc.go
#EXPOSE 8888
#
#CMD ["./schisandra-ai-server"]
FROM debian:bullseye-slim AS runtime
ENV TZ=Asia/Shanghai \
DEBIAN_FRONTEND=noninteractive
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone && \
apt-get update && apt-get install -y --no-install-recommends \
tzdata libjpeg62-turbo libpng16-16 libtiff5 libturbojpeg0 \
libharfbuzz0b libfreetype6 libavcodec58 libavformat58 libswscale5 libtbb2 \
libblas3 liblapack3 && \
rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=builder /usr/local/lib /usr/local/lib/
COPY --from=builder /usr/lib/ /usr/lib/
COPY --from=builder /usr/local/include/opencv4 /usr/local/include/opencv4/
COPY --from=builder /app/schisandra-ai-server .
COPY --from=builder /app/app/aisvc/rpc/etc ./rpc/etc
COPY --from=builder /app/app/aisvc/resources ./resources
ENV LD_LIBRARY_PATH=/usr/local/lib
RUN echo "/usr/local/lib" > /etc/ld.so.conf.d/custom-libs.conf && ldconfig
EXPOSE 8888
CMD ["./schisandra-ai-server"]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -4,15 +4,35 @@ package ai;
option go_package = "./pb";
// 人脸识别
message FaceRecognitionRequest {
bytes face = 1;
string user_id = 2;
}
message FaceRecognitionResponse {
int64 face_id = 1;
int64 face_id = 3;
}
// tf分类识别
message TfClassificationRequest {
bytes image = 1;
}
message TfClassificationResponse {
string class_name = 2;
float score = 3;
}
// caffe分类识别
message CaffeClassificationRequest {
bytes image = 1;
}
message CaffeClassificationResponse {
string class_name = 2;
float score = 3;
}
service AiService {
// FaceRecognition
rpc FaceRecognition (FaceRecognitionRequest) returns (FaceRecognitionResponse);
// TfClassification
rpc TfClassification (TfClassificationRequest) returns (TfClassificationResponse);
// CaffeClassification
rpc CaffeClassification (CaffeClassificationRequest) returns (CaffeClassificationResponse);
}

View File

@@ -14,12 +14,20 @@ import (
)
type (
CaffeClassificationRequest = pb.CaffeClassificationRequest
CaffeClassificationResponse = pb.CaffeClassificationResponse
FaceRecognitionRequest = pb.FaceRecognitionRequest
FaceRecognitionResponse = pb.FaceRecognitionResponse
TfClassificationRequest = pb.TfClassificationRequest
TfClassificationResponse = pb.TfClassificationResponse
AiService interface {
// FaceRecognition
FaceRecognition(ctx context.Context, in *FaceRecognitionRequest, opts ...grpc.CallOption) (*FaceRecognitionResponse, error)
// TfClassification
TfClassification(ctx context.Context, in *TfClassificationRequest, opts ...grpc.CallOption) (*TfClassificationResponse, error)
// CaffeClassification
CaffeClassification(ctx context.Context, in *CaffeClassificationRequest, opts ...grpc.CallOption) (*CaffeClassificationResponse, error)
}
defaultAiService struct {
@@ -38,3 +46,15 @@ func (m *defaultAiService) FaceRecognition(ctx context.Context, in *FaceRecognit
client := pb.NewAiServiceClient(m.cli.Conn())
return client.FaceRecognition(ctx, in, opts...)
}
// TfClassification
func (m *defaultAiService) TfClassification(ctx context.Context, in *TfClassificationRequest, opts ...grpc.CallOption) (*TfClassificationResponse, error) {
client := pb.NewAiServiceClient(m.cli.Conn())
return client.TfClassification(ctx, in, opts...)
}
// CaffeClassification
func (m *defaultAiService) CaffeClassification(ctx context.Context, in *CaffeClassificationRequest, opts ...grpc.CallOption) (*CaffeClassificationResponse, error) {
client := pb.NewAiServiceClient(m.cli.Conn())
return client.CaffeClassification(ctx, in, opts...)
}

View File

@@ -1,9 +1,11 @@
Name: aisvc.rpc
ListenOn: 0.0.0.0:8080
ListenOn: 0.0.0.0:8888
Etcd:
Hosts:
- 127.0.0.1:2379
- 1.95.0.111:2379
Key: aisvc.rpc
User: root
Pass: LDQ20020618xxx
# MySQL 配置
Mysql:
# 数据源dsn

View File

@@ -0,0 +1,31 @@
package aiservicelogic
import (
"context"
"schisandra-album-cloud-microservices/app/aisvc/rpc/internal/svc"
"schisandra-album-cloud-microservices/app/aisvc/rpc/pb"
"github.com/zeromicro/go-zero/core/logx"
)
type CaffeClassificationLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewCaffeClassificationLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CaffeClassificationLogic {
return &CaffeClassificationLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
// CaffeClassification
func (l *CaffeClassificationLogic) CaffeClassification(in *pb.CaffeClassificationRequest) (*pb.CaffeClassificationResponse, error) {
// todo: add your logic here and delete this line
return &pb.CaffeClassificationResponse{}, nil
}

View File

@@ -43,8 +43,12 @@ func NewFaceRecognitionLogic(ctx context.Context, svcCtx *svc.ServiceContext) *F
// FaceRecognition 人脸识别
func (l *FaceRecognitionLogic) FaceRecognition(in *pb.FaceRecognitionRequest) (*pb.FaceRecognitionResponse, error) {
toJPEG, err := l.ConvertImageToJPEG(in.GetFace())
if err != nil {
return nil, err
}
// 提取人脸特征
faceFeatures, err := l.svcCtx.FaceRecognizer.RecognizeSingle(in.GetFace())
faceFeatures, err := l.svcCtx.FaceRecognizer.RecognizeSingle(toJPEG)
if err != nil {
return nil, err
}
@@ -82,7 +86,7 @@ func (l *FaceRecognitionLogic) FaceRecognition(in *pb.FaceRecognitionRequest) (*
// 人脸分类
classify := l.svcCtx.FaceRecognizer.ClassifyThreshold(faceFeatures.Descriptor, 0.6)
if classify >= 0 {
if classify >= 0 && classify < len(ids) {
return &pb.FaceRecognitionResponse{
FaceId: int64(ids[classify]),
}, nil
@@ -92,6 +96,26 @@ func (l *FaceRecognitionLogic) FaceRecognition(in *pb.FaceRecognitionRequest) (*
return l.saveNewFace(in, faceFeatures, hashKey)
}
// ConvertImageToJPEG 将非 JPEG 格式的图片字节数据转换为 JPEG
func (l *FaceRecognitionLogic) ConvertImageToJPEG(imageData []byte) ([]byte, error) {
// 使用 image.Decode 解码图像数据
img, _, err := image.Decode(bytes.NewReader(imageData))
if err != nil {
return nil, fmt.Errorf("failed to decode image: %v", err)
}
// 创建一个缓冲区来存储 JPEG 格式的数据
var jpegBuffer bytes.Buffer
// 将图片编码为 JPEG 格式
err = jpeg.Encode(&jpegBuffer, img, nil)
if err != nil {
return nil, fmt.Errorf("failed to encode image to JPEG: %v", err)
}
return jpegBuffer.Bytes(), nil
}
// 保存新的人脸样本到数据库和 Redis
func (l *FaceRecognitionLogic) saveNewFace(in *pb.FaceRecognitionRequest, faceFeatures *face.Face, hashKey string) (*pb.FaceRecognitionResponse, error) {
// 人脸有效性判断 (大小必须大于50)

View File

@@ -0,0 +1,79 @@
package aiservicelogic
import (
"context"
"fmt"
"gocv.io/x/gocv"
"image"
"schisandra-album-cloud-microservices/app/aisvc/rpc/internal/svc"
"schisandra-album-cloud-microservices/app/aisvc/rpc/pb"
"github.com/zeromicro/go-zero/core/logx"
)
type TfClassificationLogic struct {
ctx context.Context
svcCtx *svc.ServiceContext
logx.Logger
}
func NewTfClassificationLogic(ctx context.Context, svcCtx *svc.ServiceContext) *TfClassificationLogic {
return &TfClassificationLogic{
ctx: ctx,
svcCtx: svcCtx,
Logger: logx.WithContext(ctx),
}
}
// TfClassification is a server endpoint to classify an image using TensorFlow.
func (l *TfClassificationLogic) TfClassification(in *pb.TfClassificationRequest) (*pb.TfClassificationResponse, error) {
className, source, err := l.ClassifyImage(in.GetImage())
if err != nil {
return nil, err
}
return &pb.TfClassificationResponse{
Score: source,
ClassName: className,
}, nil
}
// ClassifyImage 从字节数据分类图像,返回分类标签和最大概率值
func (l *TfClassificationLogic) ClassifyImage(imageBytes []byte) (string, float32, error) {
// 解码字节数据为图像
img, err := gocv.IMDecode(imageBytes, gocv.IMReadColor)
if err != nil || img.Empty() {
return "", 0, fmt.Errorf("failed to decode image: %v", err)
}
defer func(img *gocv.Mat) {
_ = img.Close()
}(&img)
// 将图像 Mat 转换为 224x224 blob以便分类器分析
blob := gocv.BlobFromImage(img, 1.0, image.Pt(224, 224), gocv.NewScalar(0, 0, 0, 0), true, false)
// 将 blob 输入分类器
l.svcCtx.TfNet.SetInput(blob, "input")
// 运行网络的正向传递
prob := l.svcCtx.TfNet.Forward("softmax2")
// 将结果重塑为 1x1000 矩阵
probMat := prob.Reshape(1, 1)
// 确定最可能的分类
_, maxVal, _, maxLoc := gocv.MinMaxLoc(probMat)
// 获取分类描述
desc := ""
if maxLoc.X < 1000 {
desc = l.svcCtx.TfDesc[maxLoc.X]
}
// 清理资源
_ = blob.Close()
_ = prob.Close()
_ = probMat.Close()
return desc, maxVal, nil
}

View File

@@ -28,3 +28,15 @@ func (s *AiServiceServer) FaceRecognition(ctx context.Context, in *pb.FaceRecogn
l := aiservicelogic.NewFaceRecognitionLogic(ctx, s.svcCtx)
return l.FaceRecognition(in)
}
// TfClassification
func (s *AiServiceServer) TfClassification(ctx context.Context, in *pb.TfClassificationRequest) (*pb.TfClassificationResponse, error) {
l := aiservicelogic.NewTfClassificationLogic(ctx, s.svcCtx)
return l.TfClassification(in)
}
// CaffeClassification
func (s *AiServiceServer) CaffeClassification(ctx context.Context, in *pb.CaffeClassificationRequest) (*pb.CaffeClassificationResponse, error) {
l := aiservicelogic.NewCaffeClassificationLogic(ctx, s.svcCtx)
return l.CaffeClassification(in)
}

View File

@@ -3,11 +3,14 @@ package svc
import (
"github.com/Kagami/go-face"
"github.com/redis/go-redis/v9"
"gocv.io/x/gocv"
"schisandra-album-cloud-microservices/app/aisvc/model/mysql"
"schisandra-album-cloud-microservices/app/aisvc/model/mysql/query"
"schisandra-album-cloud-microservices/app/aisvc/rpc/internal/config"
"schisandra-album-cloud-microservices/common/caffe_classifier"
"schisandra-album-cloud-microservices/common/face_recognizer"
"schisandra-album-cloud-microservices/common/redisx"
"schisandra-album-cloud-microservices/common/tf_classifier"
)
type ServiceContext struct {
@@ -15,15 +18,25 @@ type ServiceContext struct {
FaceRecognizer *face.Recognizer
DB *query.Query
RedisClient *redis.Client
TfNet *gocv.Net
TfDesc []string
CaffeNet *gocv.Net
CaffeDesc []string
}
func NewServiceContext(c config.Config) *ServiceContext {
redisClient := redisx.NewRedis(c.RedisConf.Host, c.RedisConf.Pass, c.RedisConf.DB)
_, queryDB := mysql.NewMySQL(c.Mysql.DataSource, c.Mysql.MaxOpenConn, c.Mysql.MaxIdleConn, redisClient)
tfClassifier, tfDesc := tf_classifier.NewTFClassifier()
caffeClassifier, caffeDesc := caffe_classifier.NewCaffeClassifier()
return &ServiceContext{
Config: c,
FaceRecognizer: face_recognizer.NewFaceRecognition(),
DB: queryDB,
RedisClient: redisClient,
TfNet: tfClassifier,
TfDesc: tfDesc,
CaffeNet: caffeClassifier,
CaffeDesc: caffeDesc,
}
}

View File

@@ -20,6 +20,7 @@ const (
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// 人脸识别
type FaceRecognitionRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -78,7 +79,7 @@ type FaceRecognitionResponse struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
FaceId int64 `protobuf:"varint,1,opt,name=face_id,json=faceId,proto3" json:"face_id,omitempty"`
FaceId int64 `protobuf:"varint,3,opt,name=face_id,json=faceId,proto3" json:"face_id,omitempty"`
}
func (x *FaceRecognitionResponse) Reset() {
@@ -118,6 +119,204 @@ func (x *FaceRecognitionResponse) GetFaceId() int64 {
return 0
}
// tf分类识别
type TfClassificationRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Image []byte `protobuf:"bytes,1,opt,name=image,proto3" json:"image,omitempty"`
}
func (x *TfClassificationRequest) Reset() {
*x = TfClassificationRequest{}
mi := &file_aisvc_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *TfClassificationRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*TfClassificationRequest) ProtoMessage() {}
func (x *TfClassificationRequest) ProtoReflect() protoreflect.Message {
mi := &file_aisvc_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use TfClassificationRequest.ProtoReflect.Descriptor instead.
func (*TfClassificationRequest) Descriptor() ([]byte, []int) {
return file_aisvc_proto_rawDescGZIP(), []int{2}
}
func (x *TfClassificationRequest) GetImage() []byte {
if x != nil {
return x.Image
}
return nil
}
type TfClassificationResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
ClassName string `protobuf:"bytes,2,opt,name=class_name,json=className,proto3" json:"class_name,omitempty"`
Score float32 `protobuf:"fixed32,3,opt,name=score,proto3" json:"score,omitempty"`
}
func (x *TfClassificationResponse) Reset() {
*x = TfClassificationResponse{}
mi := &file_aisvc_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *TfClassificationResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*TfClassificationResponse) ProtoMessage() {}
func (x *TfClassificationResponse) ProtoReflect() protoreflect.Message {
mi := &file_aisvc_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use TfClassificationResponse.ProtoReflect.Descriptor instead.
func (*TfClassificationResponse) Descriptor() ([]byte, []int) {
return file_aisvc_proto_rawDescGZIP(), []int{3}
}
func (x *TfClassificationResponse) GetClassName() string {
if x != nil {
return x.ClassName
}
return ""
}
func (x *TfClassificationResponse) GetScore() float32 {
if x != nil {
return x.Score
}
return 0
}
// caffe分类识别
type CaffeClassificationRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Image []byte `protobuf:"bytes,1,opt,name=image,proto3" json:"image,omitempty"`
}
func (x *CaffeClassificationRequest) Reset() {
*x = CaffeClassificationRequest{}
mi := &file_aisvc_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CaffeClassificationRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CaffeClassificationRequest) ProtoMessage() {}
func (x *CaffeClassificationRequest) ProtoReflect() protoreflect.Message {
mi := &file_aisvc_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CaffeClassificationRequest.ProtoReflect.Descriptor instead.
func (*CaffeClassificationRequest) Descriptor() ([]byte, []int) {
return file_aisvc_proto_rawDescGZIP(), []int{4}
}
func (x *CaffeClassificationRequest) GetImage() []byte {
if x != nil {
return x.Image
}
return nil
}
type CaffeClassificationResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
ClassName string `protobuf:"bytes,2,opt,name=class_name,json=className,proto3" json:"class_name,omitempty"`
Score float32 `protobuf:"fixed32,3,opt,name=score,proto3" json:"score,omitempty"`
}
func (x *CaffeClassificationResponse) Reset() {
*x = CaffeClassificationResponse{}
mi := &file_aisvc_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CaffeClassificationResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CaffeClassificationResponse) ProtoMessage() {}
func (x *CaffeClassificationResponse) ProtoReflect() protoreflect.Message {
mi := &file_aisvc_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CaffeClassificationResponse.ProtoReflect.Descriptor instead.
func (*CaffeClassificationResponse) Descriptor() ([]byte, []int) {
return file_aisvc_proto_rawDescGZIP(), []int{5}
}
func (x *CaffeClassificationResponse) GetClassName() string {
if x != nil {
return x.ClassName
}
return ""
}
func (x *CaffeClassificationResponse) GetScore() float32 {
if x != nil {
return x.Score
}
return 0
}
var File_aisvc_proto protoreflect.FileDescriptor
var file_aisvc_proto_rawDesc = []byte{
@@ -128,15 +327,42 @@ var file_aisvc_proto_rawDesc = []byte{
0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x32, 0x0a, 0x17, 0x46, 0x61, 0x63, 0x65,
0x52, 0x65, 0x63, 0x6f, 0x67, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01,
0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x66, 0x61, 0x63, 0x65, 0x49, 0x64, 0x32, 0x57, 0x0a, 0x09,
0x41, 0x69, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4a, 0x0a, 0x0f, 0x46, 0x61, 0x63,
0x65, 0x52, 0x65, 0x63, 0x6f, 0x67, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x2e, 0x61,
0x69, 0x2e, 0x46, 0x61, 0x63, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x67, 0x6e, 0x69, 0x74, 0x69, 0x6f,
0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x61, 0x69, 0x2e, 0x46, 0x61,
0x63, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x67, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03,
0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x66, 0x61, 0x63, 0x65, 0x49, 0x64, 0x22, 0x2f, 0x0a, 0x17,
0x54, 0x66, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x22, 0x4f, 0x0a,
0x18, 0x54, 0x66, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x61,
0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63,
0x6c, 0x61, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x72,
0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x32,
0x0a, 0x1a, 0x43, 0x61, 0x66, 0x66, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x63,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05,
0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x69, 0x6d, 0x61,
0x67, 0x65, 0x22, 0x52, 0x0a, 0x1b, 0x43, 0x61, 0x66, 0x66, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73,
0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65,
0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52,
0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x32, 0xfe, 0x01, 0x0a, 0x09, 0x41, 0x69, 0x53, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x12, 0x4a, 0x0a, 0x0f, 0x46, 0x61, 0x63, 0x65, 0x52, 0x65, 0x63, 0x6f,
0x67, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x2e, 0x61, 0x69, 0x2e, 0x46, 0x61, 0x63,
0x65, 0x52, 0x65, 0x63, 0x6f, 0x67, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x61, 0x69, 0x2e, 0x46, 0x61, 0x63, 0x65, 0x52, 0x65, 0x63,
0x6f, 0x67, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x12, 0x4d, 0x0a, 0x10, 0x54, 0x66, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x63, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x2e, 0x61, 0x69, 0x2e, 0x54, 0x66, 0x43, 0x6c, 0x61, 0x73,
0x73, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x69, 0x2e, 0x54, 0x66, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66,
0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
0x56, 0x0a, 0x13, 0x43, 0x61, 0x66, 0x66, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69,
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x61, 0x69, 0x2e, 0x43, 0x61, 0x66, 0x66,
0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x61, 0x69, 0x2e, 0x43, 0x61, 0x66, 0x66,
0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -151,16 +377,24 @@ func file_aisvc_proto_rawDescGZIP() []byte {
return file_aisvc_proto_rawDescData
}
var file_aisvc_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_aisvc_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_aisvc_proto_goTypes = []any{
(*FaceRecognitionRequest)(nil), // 0: ai.FaceRecognitionRequest
(*FaceRecognitionResponse)(nil), // 1: ai.FaceRecognitionResponse
(*TfClassificationRequest)(nil), // 2: ai.TfClassificationRequest
(*TfClassificationResponse)(nil), // 3: ai.TfClassificationResponse
(*CaffeClassificationRequest)(nil), // 4: ai.CaffeClassificationRequest
(*CaffeClassificationResponse)(nil), // 5: ai.CaffeClassificationResponse
}
var file_aisvc_proto_depIdxs = []int32{
0, // 0: ai.AiService.FaceRecognition:input_type -> ai.FaceRecognitionRequest
1, // 1: ai.AiService.FaceRecognition:output_type -> ai.FaceRecognitionResponse
1, // [1:2] is the sub-list for method output_type
0, // [0:1] is the sub-list for method input_type
2, // 1: ai.AiService.TfClassification:input_type -> ai.TfClassificationRequest
4, // 2: ai.AiService.CaffeClassification:input_type -> ai.CaffeClassificationRequest
1, // 3: ai.AiService.FaceRecognition:output_type -> ai.FaceRecognitionResponse
3, // 4: ai.AiService.TfClassification:output_type -> ai.TfClassificationResponse
5, // 5: ai.AiService.CaffeClassification:output_type -> ai.CaffeClassificationResponse
3, // [3:6] is the sub-list for method output_type
0, // [0:3] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
@@ -177,7 +411,7 @@ func file_aisvc_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_aisvc_proto_rawDesc,
NumEnums: 0,
NumMessages: 2,
NumMessages: 6,
NumExtensions: 0,
NumServices: 1,
},

View File

@@ -20,6 +20,8 @@ const _ = grpc.SupportPackageIsVersion9
const (
AiService_FaceRecognition_FullMethodName = "/ai.AiService/FaceRecognition"
AiService_TfClassification_FullMethodName = "/ai.AiService/TfClassification"
AiService_CaffeClassification_FullMethodName = "/ai.AiService/CaffeClassification"
)
// AiServiceClient is the client API for AiService service.
@@ -28,6 +30,10 @@ const (
type AiServiceClient interface {
// FaceRecognition
FaceRecognition(ctx context.Context, in *FaceRecognitionRequest, opts ...grpc.CallOption) (*FaceRecognitionResponse, error)
// TfClassification
TfClassification(ctx context.Context, in *TfClassificationRequest, opts ...grpc.CallOption) (*TfClassificationResponse, error)
// CaffeClassification
CaffeClassification(ctx context.Context, in *CaffeClassificationRequest, opts ...grpc.CallOption) (*CaffeClassificationResponse, error)
}
type aiServiceClient struct {
@@ -48,12 +54,36 @@ func (c *aiServiceClient) FaceRecognition(ctx context.Context, in *FaceRecogniti
return out, nil
}
func (c *aiServiceClient) TfClassification(ctx context.Context, in *TfClassificationRequest, opts ...grpc.CallOption) (*TfClassificationResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(TfClassificationResponse)
err := c.cc.Invoke(ctx, AiService_TfClassification_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *aiServiceClient) CaffeClassification(ctx context.Context, in *CaffeClassificationRequest, opts ...grpc.CallOption) (*CaffeClassificationResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(CaffeClassificationResponse)
err := c.cc.Invoke(ctx, AiService_CaffeClassification_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// AiServiceServer is the server API for AiService service.
// All implementations must embed UnimplementedAiServiceServer
// for forward compatibility.
type AiServiceServer interface {
// FaceRecognition
FaceRecognition(context.Context, *FaceRecognitionRequest) (*FaceRecognitionResponse, error)
// TfClassification
TfClassification(context.Context, *TfClassificationRequest) (*TfClassificationResponse, error)
// CaffeClassification
CaffeClassification(context.Context, *CaffeClassificationRequest) (*CaffeClassificationResponse, error)
mustEmbedUnimplementedAiServiceServer()
}
@@ -67,6 +97,12 @@ type UnimplementedAiServiceServer struct{}
func (UnimplementedAiServiceServer) FaceRecognition(context.Context, *FaceRecognitionRequest) (*FaceRecognitionResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method FaceRecognition not implemented")
}
func (UnimplementedAiServiceServer) TfClassification(context.Context, *TfClassificationRequest) (*TfClassificationResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method TfClassification not implemented")
}
func (UnimplementedAiServiceServer) CaffeClassification(context.Context, *CaffeClassificationRequest) (*CaffeClassificationResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CaffeClassification not implemented")
}
func (UnimplementedAiServiceServer) mustEmbedUnimplementedAiServiceServer() {}
func (UnimplementedAiServiceServer) testEmbeddedByValue() {}
@@ -106,6 +142,42 @@ func _AiService_FaceRecognition_Handler(srv interface{}, ctx context.Context, de
return interceptor(ctx, in, info, handler)
}
func _AiService_TfClassification_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(TfClassificationRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AiServiceServer).TfClassification(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: AiService_TfClassification_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AiServiceServer).TfClassification(ctx, req.(*TfClassificationRequest))
}
return interceptor(ctx, in, info, handler)
}
func _AiService_CaffeClassification_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CaffeClassificationRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AiServiceServer).CaffeClassification(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: AiService_CaffeClassification_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AiServiceServer).CaffeClassification(ctx, req.(*CaffeClassificationRequest))
}
return interceptor(ctx, in, info, handler)
}
// AiService_ServiceDesc is the grpc.ServiceDesc for AiService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@@ -117,6 +189,14 @@ var AiService_ServiceDesc = grpc.ServiceDesc{
MethodName: "FaceRecognition",
Handler: _AiService_FaceRecognition_Handler,
},
{
MethodName: "TfClassification",
Handler: _AiService_TfClassification_Handler,
},
{
MethodName: "CaffeClassification",
Handler: _AiService_CaffeClassification_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "aisvc.proto",

View File

@@ -433,7 +433,7 @@ type (
@server (
group: storage // 微服务分组
prefix: /api/auth/storage // 微服务前缀
timeout: 10s // 超时时间
timeout: 20s // 超时时间
maxBytes: 104857600 // 最大请求大小
signature: false // 是否开启签名验证
middleware: SecurityHeadersMiddleware,CasbinVerifyMiddleware,AuthorizationMiddleware,NonceMiddleware // 注册中间件

View File

@@ -22,8 +22,10 @@ Verbose: false
AiSvcRpc:
Etcd:
Hosts:
- 127.0.0.1:2379
- 1.95.0.111:2379
Key: aisvc.rpc
User: root
Pass: LDQ20020618xxx
# 日志配置
Log:
# 服务名称

View File

@@ -202,7 +202,7 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
),
rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
rest.WithPrefix("/api/auth/storage"),
rest.WithTimeout(10000*time.Millisecond),
rest.WithTimeout(20000*time.Millisecond),
rest.WithMaxBytes(104857600),
)

View File

@@ -69,6 +69,13 @@ func (l *UploadFileLogic) UploadFile(r *http.Request) (resp string, err error) {
if face != nil {
faceId = face.GetFaceId()
}
// 分类
classification, err := l.svcCtx.AiSvcRpc.TfClassification(l.ctx, &pb.TfClassificationRequest{Image: bytes})
if err != nil {
return "", err
}
fmt.Println(classification.ClassName)
fmt.Println(classification.Score)
// 解析 EXIF 信息
exif, err := l.parseExifData(result.Exif)

View File

@@ -1,120 +0,0 @@
# to build this docker image:
# docker build -f opencv.Dockerfile -t schisandra-cloud-album-server .
# docker build --build-arg OPENCV_VERSION="4.x" --build-arg OPENCV_FILE="https://github.com/opencv/opencv/archive/refs/heads/4.x.zip" --build-arg OPENCV_CONTRIB_FILE="https://github.com/opencv/opencv_contrib/archive/refs/heads/4.x.zip" -f opencv.Dockerfile -t schisandra-cloud-album-server .
FROM ubuntu:20.04 AS opencv-builder
LABEL maintainer="landaiqing <<landaiqing@126.com>>"
RUN sed -i 's|http://archive.ubuntu.com/ubuntu/|http://mirrors.aliyun.com/ubuntu/|g' /etc/apt/sources.list
ENV TZ=Europe/Madrid
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN apt-get update && apt-get install -y --no-install-recommends --fix-missing \
tzdata git build-essential cmake pkg-config wget unzip libgtk2.0-dev \
curl ca-certificates libcurl4-openssl-dev libssl-dev \
libavcodec-dev libavformat-dev libswscale-dev libtbb2 libtbb-dev \
libharfbuzz-dev libfreetype6-dev \
libjpeg-turbo8-dev libpng-dev libtiff-dev libdc1394-22-dev nasm && \
rm -rf /var/lib/apt/lists/*
ARG OPENCV_VERSION="4.10.0"
ENV OPENCV_VERSION=$OPENCV_VERSION
ARG OPENCV_FILE="https://github.com/opencv/opencv/archive/${OPENCV_VERSION}.zip"
ENV OPENCV_FILE=$OPENCV_FILE
ARG OPENCV_CONTRIB_FILE="https://github.com/opencv/opencv_contrib/archive/${OPENCV_VERSION}.zip"
ENV OPENCV_CONTRIB_FILE=$OPENCV_CONTRIB_FILE
RUN curl -Lo opencv.zip ${OPENCV_FILE} && \
unzip -q opencv.zip && \
curl -Lo opencv_contrib.zip ${OPENCV_CONTRIB_FILE} && \
unzip -q opencv_contrib.zip && \
rm opencv.zip opencv_contrib.zip && \
cd opencv-${OPENCV_VERSION} && \
mkdir build && cd build && \
cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D WITH_IPP=OFF \
-D WITH_OPENGL=OFF \
-D WITH_QT=OFF \
-D WITH_FREETYPE=ON \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib-${OPENCV_VERSION}/modules \
-D OPENCV_ENABLE_NONFREE=ON \
-D WITH_JASPER=OFF \
-D WITH_TBB=ON \
-D BUILD_JPEG=ON \
-D WITH_SIMD=ON \
-D ENABLE_LIBJPEG_TURBO_SIMD=ON \
-D BUILD_DOCS=OFF \
-D BUILD_EXAMPLES=OFF \
-D BUILD_TESTS=OFF \
-D BUILD_PERF_TESTS=ON \
-D BUILD_opencv_java=NO \
-D BUILD_opencv_python=NO \
-D BUILD_opencv_python2=NO \
-D BUILD_opencv_python3=NO \
-D OPENCV_GENERATE_PKGCONFIG=ON .. && \
make -j $(nproc --all) && \
make preinstall && make install && ldconfig && \
cd / && rm -rf opencv*
FROM golang:1.23.1-alpine AS go-builder
RUN apk add --no-cache gcc musl-dev libgcc libstdc++ cmake
WORKDIR /app
COPY . .
ENV CGO_ENABLED=1
ENV CGO_CFLAGS="-I/usr/local/include/opencv4"
ENV CGO_LDFLAGS="-L/usr/local/lib -lopencv_core -lopencv_imgproc -lopencv_highgui"
ENV GOOS=linux
ENV GOARCH=amd64
ENV GOPROXY=https://goproxy.cn,direct
COPY --from=opencv-builder /usr/local/lib /usr/local/lib
COPY --from=opencv-builder /usr/local/include/opencv4 /usr/local/include/opencv4
RUN go mod download
RUN go build -o schisandra-cloud-album-server
FROM alpine:latest
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
RUN apk add --no-cache tzdata
ENV TZ=Asia/Shanghai
WORKDIR /app
COPY --from=go-builder /app/schisandra-cloud-album-server .
COPY --from=go-builder /app/config.yaml .
COPY --from=go-builder /app/resource ./resource
COPY --from=go-builder /app/config/rbac_model.conf ./config/rbac_model.conf
COPY --from=opencv-builder /usr/local/lib /usr/local/lib
COPY --from=opencv-builder /usr/local/include/opencv4 /usr/local/include/opencv4
EXPOSE 80
CMD ["./schisandra-cloud-album-server"]

46
auth.Dockerfile Normal file
View File

@@ -0,0 +1,46 @@
# to build this docker image:
# docker build -f auth.Dockerfile -t schisandra-auth-server .
FROM golang:1.23.5-bullseye AS builder
LABEL maintainer="landaiqing <<landaiqing@126.com>>"
ENV TZ=Asia/Shanghai \
DEBIAN_FRONTEND=noninteractive
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
WORKDIR /app
COPY . .
ENV CGO_ENABLED=0 \
GOOS=linux \
GOARCH=amd64 \
GOPROXY=https://goproxy.cn,direct
RUN go mod download && \
go build -ldflags="-w -s" -o schisandra-auth-server ./app/auth/api/auth.go
FROM alpine:latest
ENV TZ=Asia/Shanghai \
DEBIAN_FRONTEND=noninteractive
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
apk add --no-cache tzdata libjpeg-turbo
WORKDIR /app
COPY --from=builder /app/schisandra-auth-server .
COPY --from=builder /app/app/auth/api/etc ./api/etc
COPY --from=builder /app/app/auth/resources ./resources
EXPOSE 80
CMD ["./schisandra-auth-server"]

View File

@@ -0,0 +1,58 @@
package caffe_classifier
import (
"bufio"
"fmt"
"gocv.io/x/gocv"
"os"
"path/filepath"
)
// NewCaffeClassifier 创建一个新的Caffe分类器
func NewCaffeClassifier() (*gocv.Net, []string) {
var err error
dir, err := os.Getwd()
// 加载模型
model := filepath.Join(dir, "/resources/models/caffemodel/bvlc_googlenet.caffemodel")
config := filepath.Join(dir, "/resources/models/caffemodel/bvlc_googlenet.prototxt")
description := filepath.Join(dir, "/resources/models/caffemodel/classification_classes_ILSVRC2012.txt")
net := gocv.ReadNet(model, config)
if net.Empty() {
panic(fmt.Errorf("error reading network model: %v", model))
}
// 设置后端和目标设备
err = net.SetPreferableBackend(gocv.NetBackendDefault)
if err != nil {
panic(fmt.Errorf("error setting preferable backend: %v", err))
}
err = net.SetPreferableTarget(gocv.NetTargetCPU)
if err != nil {
panic(fmt.Errorf("error setting preferable target: %v", err))
}
// 加载描述文件
descriptions, err := readDescriptions(description)
if err != nil {
panic(fmt.Errorf("error reading descriptions: %v", err))
}
return &net, descriptions
}
// readDescriptions reads the descriptions from a file
// and returns a slice of its lines.
func readDescriptions(path string) ([]string, error) {
file, err := os.Open(filepath.Clean(path))
if err != nil {
return nil, err
}
defer func() {
_ = file.Close()
}()
var lines []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
return lines, scanner.Err()
}

View File

@@ -0,0 +1,56 @@
package tf_classifier
import (
"bufio"
"fmt"
"gocv.io/x/gocv"
"os"
"path/filepath"
)
// NewTFClassifier 创建一个新的TFClassifier实例
func NewTFClassifier() (*gocv.Net, []string) {
var err error
dir, err := os.Getwd()
// 加载模型
model := filepath.Join(dir, "/resources/models/tf_classifier/inception5h/tensorflow_inception_graph.pb")
description := filepath.Join(dir, "/resources/models/tf_classifier/inception5h/imagenet_comp_graph_label_strings.txt")
net := gocv.ReadNet(model, "")
if net.Empty() {
panic(fmt.Errorf("error reading network model: %v", model))
}
// 设置后端和目标设备
err = net.SetPreferableBackend(gocv.NetBackendDefault)
if err != nil {
panic(fmt.Errorf("error setting preferable backend: %v", err))
}
err = net.SetPreferableTarget(gocv.NetTargetCPU)
if err != nil {
panic(fmt.Errorf("error setting preferable target: %v", err))
}
// 加载描述文件
descriptions, err := ReadDescriptions(description)
if err != nil {
panic(fmt.Errorf("error reading descriptions: %v", err))
}
return &net, descriptions
}
// ReadDescriptions 从文件中读取描述并返回其行的切片
func ReadDescriptions(path string) ([]string, error) {
file, err := os.Open(filepath.Clean(path))
if err != nil {
return nil, err
}
defer func() {
_ = file.Close()
}()
var lines []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
return lines, scanner.Err()
}

9
go.mod
View File

@@ -5,12 +5,14 @@ go 1.23.4
require (
github.com/ArtisanCloud/PowerLibs/v3 v3.3.1
github.com/ArtisanCloud/PowerWeChat/v3 v3.3.3
github.com/Kagami/go-face v0.0.0-20210630145111-0c14797b4d0e
github.com/aliyun/alibabacloud-oss-go-sdk-v2 v1.2.0
github.com/asjdf/gorm-cache v1.2.3
github.com/casbin/casbin/v2 v2.103.0
github.com/casbin/gorm-adapter/v3 v3.32.0
github.com/ccpwcn/kgo v1.2.8
github.com/chenmingyong0423/go-mongox/v2 v2.0.0
github.com/corona10/goimagehash v1.1.0
github.com/duke-git/lancet/v2 v2.3.4
github.com/golang-jwt/jwt/v5 v5.2.1
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
@@ -29,6 +31,7 @@ require (
github.com/zeromicro/go-zero v1.7.6
github.com/zmexing/go-sensitive-word v1.3.0
go.mongodb.org/mongo-driver/v2 v2.0.0
gocv.io/x/gocv v0.40.0
golang.org/x/crypto v0.32.0
golang.org/x/text v0.21.0
google.golang.org/grpc v1.69.4
@@ -43,7 +46,6 @@ require (
require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/ArtisanCloud/PowerSocialite/v3 v3.0.7 // indirect
github.com/Kagami/go-face v0.0.0-20210630145111-0c14797b4d0e // indirect
github.com/andybalholm/brotli v1.1.1 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
@@ -57,7 +59,6 @@ require (
github.com/cloudflare/circl v1.5.0 // indirect
github.com/coreos/go-semver v0.3.1 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/corona10/goimagehash v1.1.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dolthub/maphash v0.1.0 // indirect
@@ -89,10 +90,10 @@ require (
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20250120214715-4e5bb2051dab // indirect
github.com/google/pprof v0.0.0-20250121033306-997b0b79cac0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/css v1.0.1 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/imroc/req/v3 v3.49.1 // indirect

78
go.sum
View File

@@ -81,9 +81,7 @@ github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/corona10/goimagehash v1.1.0 h1:teNMX/1e+Wn/AYSbLHX8mj+mF9r60R1kBeqE9MkoYwI=
github.com/corona10/goimagehash v1.1.0/go.mod h1:VkvE0mLn84L4aF8vCb6mafVajEb6QYMHl2ZJLn0mOGI=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -97,8 +95,6 @@ github.com/duke-git/lancet/v2 v2.3.4 h1:8XGI7P9w+/GqmEBEXYaH/XuNiM0f4/90Ioti0IvY
github.com/duke-git/lancet/v2 v2.3.4/go.mod h1:zGa2R4xswg6EG9I6WnyubDbFO/+A/RROxIbXcwryTsc=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU=
github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
@@ -113,22 +109,14 @@ github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GM
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
github.com/go-bindata/go-bindata v3.1.2+incompatible/go.mod h1:xK8Dsgwmeed+BBsSy2XTopBn/8uK2HWuGSnA11C3Joo=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
@@ -167,8 +155,6 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@@ -181,10 +167,10 @@ github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/pprof v0.0.0-20250120214715-4e5bb2051dab h1:FcOz+Hn0n9Ek4Ij6mvYUhvHGg0+EhV9ImR+PMmTP0S0=
github.com/google/pprof v0.0.0-20250120214715-4e5bb2051dab/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/pprof v0.0.0-20250121033306-997b0b79cac0 h1:EinjE47mmVVsxcjIwVKQWNY+3P+5R2BhkbULjhEDThc=
github.com/google/pprof v0.0.0-20250121033306-997b0b79cac0/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -197,6 +183,8 @@ github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/z
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0 h1:VD1gqscl4nYs1YxVuSdemTrSgTKrwOWDK0FVFMqm+Cg=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0/go.mod h1:4EgsQoS4TOhJizV+JTFg40qx1Ofh3XmXEQNBpgvNT40=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@@ -236,11 +224,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
@@ -253,8 +238,6 @@ github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20241220152942-06eb5c6e8
github.com/lionsoul2014/ip2region/binding/golang v0.0.0-20241220152942-06eb5c6e8230/go.mod h1:C5LA5UO2ZXJrLaPLYtE1wUJMiyd/nwWaCO5cw/2pSHs=
github.com/lxzan/gws v1.8.8 h1:st193ZG8qN8sSw8/g/UituFhs7etmKzS7jUqhijg5wM=
github.com/lxzan/gws v1.8.8/go.mod h1:FcGeRMB7HwGuTvMLR24ku0Zx0p6RXqeKASeMc4VYgi4=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
@@ -313,16 +296,15 @@ github.com/pkg6/go-requests v0.2.3 h1:IwlH6D1DlIKnBaLccz4dJR75CCoPEw4HD7BST9sD5k
github.com/pkg6/go-requests v0.2.3/go.mod h1:/rcVm8Itd2djtxDVxjRnHURChV86TB4ooZnP+IBZBmg=
github.com/pkg6/go-sms v0.1.2 h1:HZQlBkRVF9xQHhyCMB3kXY/kltfvuNgMTKuN/DoSg7w=
github.com/pkg6/go-sms v0.1.2/go.mod h1:PwFBEssnkYXw+mfSmQ+6fwgXgrcUB9NK5dLUglx+ZW4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ=
github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s=
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
@@ -389,60 +371,36 @@ github.com/zeromicro/go-zero v1.7.6 h1:SArK4xecdrpVY3ZFJcbc0IZCx+NuWyHNjCv9f1+Gw
github.com/zeromicro/go-zero v1.7.6/go.mod h1:SmGykRm5e0Z4CGNj+GaSKDffaHzQV56fel0FkymTLlE=
github.com/zmexing/go-sensitive-word v1.3.0 h1:dB9S9kNklksOODGLLAov0RaVCwC2w9Kwxz6NZMdM6rk=
github.com/zmexing/go-sensitive-word v1.3.0/go.mod h1:wkNIpkq1iPOe3l7l83zvnnV5mm20jfj2x8V8kjOTsUM=
go.etcd.io/etcd/api/v3 v3.5.15 h1:3KpLJir1ZEBrYuV2v+Twaa/e2MdDCEZ/70H+lzEiwsk=
go.etcd.io/etcd/api/v3 v3.5.15/go.mod h1:N9EhGzXq58WuMllgH9ZvnEr7SI9pS0k0+DHZezGp7jM=
go.etcd.io/etcd/api/v3 v3.5.17 h1:cQB8eb8bxwuxOilBpMJAEo8fAONyrdXTHUNcMd8yT1w=
go.etcd.io/etcd/api/v3 v3.5.17/go.mod h1:d1hvkRuXkts6PmaYk2Vrgqbv7H4ADfAKhyJqHNLJCB4=
go.etcd.io/etcd/client/pkg/v3 v3.5.15 h1:fo0HpWz/KlHGMCC+YejpiCmyWDEuIpnTDzpJLB5fWlA=
go.etcd.io/etcd/client/pkg/v3 v3.5.15/go.mod h1:mXDI4NAOwEiszrHCb0aqfAYNCrZP4e9hRca3d1YK8EU=
go.etcd.io/etcd/client/pkg/v3 v3.5.17 h1:XxnDXAWq2pnxqx76ljWwiQ9jylbpC4rvkAeRVOUKKVw=
go.etcd.io/etcd/client/pkg/v3 v3.5.17/go.mod h1:4DqK1TKacp/86nJk4FLQqo6Mn2vvQFBmruW3pP14H/w=
go.etcd.io/etcd/client/v3 v3.5.15 h1:23M0eY4Fd/inNv1ZfU3AxrbbOdW79r9V9Rl62Nm6ip4=
go.etcd.io/etcd/client/v3 v3.5.15/go.mod h1:CLSJxrYjvLtHsrPKsy7LmZEE+DK2ktfd2bN4RhBMwlU=
go.etcd.io/etcd/client/v3 v3.5.17 h1:o48sINNeWz5+pjy/Z0+HKpj/xSnBkuVhVvXkjEXbqZY=
go.etcd.io/etcd/client/v3 v3.5.17/go.mod h1:j2d4eXTHWkT2ClBgnnEPm/Wuu7jsqku41v9DZ3OtjQo=
go.mongodb.org/mongo-driver/v2 v2.0.0 h1:Jfd7XpdZa9yk3eY774bO7SWVb30noLSirL9nKTpavhI=
go.mongodb.org/mongo-driver/v2 v2.0.0/go.mod h1:nSjmNq4JUstE8IRZKTktLgMHM4F1fccL6HGX1yh+8RA=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw=
go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I=
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
go.opentelemetry.io/otel/exporters/jaeger v1.17.0 h1:D7UpUy2Xc2wsi1Ras6V40q806WM07rqoCWzXu7Sqy+4=
go.opentelemetry.io/otel/exporters/jaeger v1.17.0/go.mod h1:nPCqOnEH9rNLKqH/+rrUjiMzHJdV1BlpKcTwRTyKkKI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 h1:Vh5HayB/0HHfOQA7Ctx69E/Y/DcQSMPpKANYVMQ7fBA=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0/go.mod h1:cpgtDBaqD/6ok/UG0jT15/uKjAY8mRA53diogHBg3UI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 h1:5pojmb1U1AogINhN3SurB+zm/nIcusopeBNp42f45QM=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0/go.mod h1:57gTHJSE5S1tqg+EKsLPlTWhpHMsWlVmer+LA926XiA=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 h1:wpMfgF8E1rkrT1Z6meFh1NDtownE9Ii3n3X2GJYjsaU=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0/go.mod h1:wAy0T/dUbs468uOlkT31xjvqQgEVXv58BRFWEgn5v/0=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 h1:BEj3SPM81McUZHYjRS5pEgNgnmzGJ5tRpU5krWnV8Bs=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0/go.mod h1:9cKLGBDzI/F3NoHLQGm4ZrYdIHsvGt6ej6hUowxY0J4=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.33.0 h1:W5AWUn/IVe8RFb5pZx1Uh9Laf/4+Qmm4kJL5zPuvR+0=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.33.0/go.mod h1:mzKxJywMNBdEX8TSJais3NnsVZUaJ+bAy6UxPTng2vk=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0 h1:jBpDk4HAUsrnVO1FsfCfCOTEc/MkInJmvfCHYLFiT80=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.34.0/go.mod h1:H9LUIM1daaeZaz91vZcfeM0fejXPmgCYE8ZhzqfJuiU=
go.opentelemetry.io/otel/exporters/zipkin v1.33.0 h1:aFexjEJIw5kVz6vQwnsqCG/nTV/UpsZh7MtQwGmH1eI=
go.opentelemetry.io/otel/exporters/zipkin v1.33.0/go.mod h1:aYsOzr/SZwZXJM6DJmSP/ST2P7MYxuc0R9RewkFVp9s=
go.opentelemetry.io/otel/exporters/zipkin v1.34.0 h1:GSjCkoYqsnvUMCjxF18j2tCWH8fhGZYjH3iYgechPTI=
go.opentelemetry.io/otel/exporters/zipkin v1.34.0/go.mod h1:h830hluwAqgSNnZbxL2rJhmAlE7/0SF9esoHVLU04Gc=
go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ=
go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M=
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
go.opentelemetry.io/otel/sdk v1.33.0 h1:iax7M131HuAm9QkZotNHEfstof92xM+N8sr3uHXc2IM=
go.opentelemetry.io/otel/sdk v1.33.0/go.mod h1:A1Q5oi7/9XaMlIWzPSxLRWOI8nG3FnzHJNbiENQuihM=
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc=
go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8=
go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s=
go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck=
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
@@ -457,6 +415,8 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
gocv.io/x/gocv v0.40.0 h1:kGBu/UVj+dO6A9dhQmGOnCICSL7ke7b5YtX3R3azdXI=
gocv.io/x/gocv v0.40.0/go.mod h1:zYdWMj29WAEznM3Y8NsU3A0TRq/wR/cy75jeUypThqU=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@@ -502,8 +462,6 @@ golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE=
golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70=
golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -561,8 +519,6 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -628,28 +584,16 @@ gorm.io/plugin/dbresolver v1.5.3 h1:wFwINGZZmttuu9h7XpvbDHd8Lf9bb8GNzp/NpAMV2wU=
gorm.io/plugin/dbresolver v1.5.3/go.mod h1:TSrVhaUg2DZAWP3PrHlDlITEJmNOkL0tFTjvTEsQ4XE=
gorm.io/plugin/optimisticlock v1.1.3 h1:uFK8zz+Ln6ju3vGkTd1LY3xR2VBmMxjdU12KBb58PBA=
gorm.io/plugin/optimisticlock v1.1.3/go.mod h1:S+MH7qnHGQHxDBc9phjgN+DpNPn/qESd1q69fA3dtkg=
k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw=
k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80=
k8s.io/api v0.32.1 h1:f562zw9cy+GvXzXf0CKlVQ7yHJVYzLfL6JAS4kOAaOc=
k8s.io/api v0.32.1/go.mod h1:/Yi/BqkuueW1BgpoePYBRdDYfjPF5sgTr5+YqDZra5k=
k8s.io/apimachinery v0.29.4 h1:RaFdJiDmuKs/8cm1M6Dh1Kvyh59YQFDcFuFTSmXes6Q=
k8s.io/apimachinery v0.29.4/go.mod h1:i3FJVwhvSp/6n8Fl4K97PJEP8C+MM+aoDq4+ZJBf70Y=
k8s.io/apimachinery v0.32.1 h1:683ENpaCBjma4CYqsmZyhEzrGz6cjn1MY/X2jB2hkZs=
k8s.io/apimachinery v0.32.1/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg=
k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0=
k8s.io/client-go v0.32.1 h1:otM0AxdhdBIaQh7l1Q0jQpmo7WOFIk5FFa4bg6YMdUU=
k8s.io/client-go v0.32.1/go.mod h1:aTTKZY7MdxUaJ/KiUs8D+GssR9zJZi77ZqtzcGXIiDg=
k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA=
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 h1:hcha5B1kVACrLujCKLbr8XWMxCxzQx42DY8QKYJrDLg=
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7/go.mod h1:GewRfANuJ70iYzvn+i4lezLDAFzvjxZYK1gn1lWcfas=
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0=
k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
modernc.org/cc/v4 v4.24.4 h1:TFkx1s6dCkQpd6dKurBNmpo+G8Zl4Sq/ztJ+2+DEsh0=
@@ -676,15 +620,9 @@ modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 h1:nbCitCK2hfnhyiKo6uf2HxUPTCodY6Qaf85SbDIaMBk=
sigs.k8s.io/structured-merge-diff/v4 v4.5.0/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=