diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..6046dc7 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,45 @@ +version: 2 +updates: + # Python (requirements.txt, pyproject.toml) + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 + + # React frontend (client/package.json) + - package-ecosystem: "npm" + directory: "/client" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 + + # GitHub Actions workflows + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + + # Docker base image - FastAPI/Celery + - package-ecosystem: "docker" + directory: "/App" + schedule: + interval: "weekly" + + # Docker base image - React/Nginx + - package-ecosystem: "docker" + directory: "/client" + schedule: + interval: "weekly" + + # Docker base image - MySQL + - package-ecosystem: "docker" + directory: "/docker/mysql" + schedule: + interval: "weekly" + + # Docker base image - Redis + - package-ecosystem: "docker" + directory: "/docker/redis" + schedule: + interval: "weekly" diff --git a/.github/labeler.yml b/.github/labeler.yml deleted file mode 100644 index 8f69fee..0000000 --- a/.github/labeler.yml +++ /dev/null @@ -1,31 +0,0 @@ -model: - - changed-files: - - any-glob-to-any-file: ["src/model/**", "models/**", "*.pt", "*.pth"] - -data: - - changed-files: - - any-glob-to-any-file: ["data/**", "datasets/**", "src/data/**"] - -training: - - changed-files: - - any-glob-to-any-file: ["train*.py", "src/train/**", "configs/**"] - -api: - - changed-files: - - any-glob-to-any-file: ["api/**", "routers/**", "app.py"] - -test: - - changed-files: - - any-glob-to-any-file: ["tests/**", "test_*.py"] - -docs: - - changed-files: - - any-glob-to-any-file: ["docs/**", "*.md", "*.rst"] - -ci: - - changed-files: - - any-glob-to-any-file: [".github/**"] - -dependencies: - - changed-files: - - any-glob-to-any-file: ["requirements*.txt", "pyproject.toml", "setup.py"] \ No newline at end of file diff --git a/.github/workflows/docker-build-check.yml b/.github/workflows/docker-build-check.yml index b07f70d..af11f2d 100644 --- a/.github/workflows/docker-build-check.yml +++ b/.github/workflows/docker-build-check.yml @@ -4,10 +4,19 @@ on: pull_request: branches: [main, develop] paths: - - "App/Dockerfile" - - "client/Dockerfile" - - "docker/mysql/Dockerfile" - - "docker/redis/Dockerfile" + # fastapi / celery (App/Dockerfile이 COPY하는 대상) + - "App/**" + - "requirements.txt" + - "deepguard/**" + - "inference/**" + - "explainability/**" + - "preprocess/**" + - "pyproject.toml" + # react (client/Dockerfile이 COPY하는 대상) + - "client/**" + # mysql / redis + - "docker/mysql/**" + - "docker/redis/**" permissions: contents: read @@ -17,69 +26,87 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v7 + with: + lfs: true - - name: Detect changed Dockerfiles + - name: Detect changed sources id: changes - uses: dorny/paths-filter@v3 + uses: dorny/paths-filter@v4 with: filters: | app: - - 'App/Dockerfile' + - 'App/**' + - 'requirements.txt' + - 'deepguard/**' + - 'inference/**' + - 'explainability/**' + - 'preprocess/**' + - 'pyproject.toml' client: - - 'client/Dockerfile' + - 'client/**' mysql: - - 'docker/mysql/Dockerfile' + - 'docker/mysql/**' + - 'App/sql/**' redis: - - 'docker/redis/Dockerfile' + - 'docker/redis/**' - name: Set up Docker Buildx if: steps.changes.outputs.app == 'true' || steps.changes.outputs.client == 'true' || steps.changes.outputs.mysql == 'true' || steps.changes.outputs.redis == 'true' - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 # ── fastapi + celery (App/Dockerfile) ──────────────────────────────────── - - name: Build fastapi/celery (validate only) + - name: Build fastapi (validate only) if: steps.changes.outputs.app == 'true' - run: | - set -euo pipefail - docker buildx build \ - --target fastapi \ - --cache-from type=gha,scope=fastapi \ - --cache-to type=gha,mode=max,scope=fastapi \ - -f App/Dockerfile . + uses: docker/build-push-action@v7 + with: + context: . + file: App/Dockerfile + target: fastapi + push: false + cache-from: type=gha,scope=fastapi + cache-to: type=gha,mode=max,scope=fastapi - docker buildx build \ - --target celery \ - --cache-from type=gha,scope=celery \ - --cache-to type=gha,mode=max,scope=celery \ - -f App/Dockerfile . + - name: Build celery (validate only) + if: steps.changes.outputs.app == 'true' + uses: docker/build-push-action@v7 + with: + context: . + file: App/Dockerfile + target: celery + push: false + cache-from: type=gha,scope=celery + cache-to: type=gha,mode=max,scope=celery # ── react (client/Dockerfile) ───────────────────────────────────────────── - name: Build react (validate only) if: steps.changes.outputs.client == 'true' - run: | - set -euo pipefail - docker buildx build \ - --cache-from type=gha,scope=react \ - --cache-to type=gha,mode=max,scope=react \ - -f client/Dockerfile client + uses: docker/build-push-action@v7 + with: + context: client + file: client/Dockerfile + push: false + cache-from: type=gha,scope=react + cache-to: type=gha,mode=max,scope=react # ── mysql (docker/mysql/Dockerfile) ─────────────────────────────────────── - name: Build mysql (validate only) if: steps.changes.outputs.mysql == 'true' - run: | - set -euo pipefail - docker buildx build \ - --cache-from type=gha,scope=mysql \ - --cache-to type=gha,mode=max,scope=mysql \ - -f docker/mysql/Dockerfile . + uses: docker/build-push-action@v7 + with: + context: . + file: docker/mysql/Dockerfile + push: false + cache-from: type=gha,scope=mysql + cache-to: type=gha,mode=max,scope=mysql # ── redis (docker/redis/Dockerfile) ─────────────────────────────────────── - name: Build redis (validate only) if: steps.changes.outputs.redis == 'true' - run: | - set -euo pipefail - docker buildx build \ - --cache-from type=gha,scope=redis \ - --cache-to type=gha,mode=max,scope=redis \ - -f docker/redis/Dockerfile . + uses: docker/build-push-action@v7 + with: + context: . + file: docker/redis/Dockerfile + push: false + cache-from: type=gha,scope=redis + cache-to: type=gha,mode=max,scope=redis diff --git a/.github/workflows/docker-bump-and-push.yml b/.github/workflows/docker-bump-and-push.yml deleted file mode 100644 index 57cb4bc..0000000 --- a/.github/workflows/docker-bump-and-push.yml +++ /dev/null @@ -1,126 +0,0 @@ -name: Docker Image Bump & Push - -# Dockerfile이 main에 push되면 해당 이미지를 새 patch 버전 태그로 빌드해 Docker Hub에 푸시한다. -# docker-compose.yml의 태그 갱신은 각 build step 로그에 찍히는 새 태그를 보고 수동으로 반영한다. - -on: - push: - branches: [main] - paths: - - "App/Dockerfile" - - "client/Dockerfile" - - "docker/mysql/Dockerfile" - - "docker/redis/Dockerfile" - workflow_dispatch: - -env: - DOCKERHUB_NAMESPACE: ${{ secrets.DOCKERHUB_USERNAME }} - -jobs: - bump-and-push: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Detect changed Dockerfiles - id: changes - uses: dorny/paths-filter@v3 - with: - filters: | - app: - - 'App/Dockerfile' - client: - - 'client/Dockerfile' - mysql: - - 'docker/mysql/Dockerfile' - redis: - - 'docker/redis/Dockerfile' - - - name: Set up Docker Buildx - if: steps.changes.outputs.app == 'true' || steps.changes.outputs.client == 'true' || steps.changes.outputs.mysql == 'true' || steps.changes.outputs.redis == 'true' - uses: docker/setup-buildx-action@v3 - - - name: Log in to Docker Hub - if: steps.changes.outputs.app == 'true' || steps.changes.outputs.client == 'true' || steps.changes.outputs.mysql == 'true' || steps.changes.outputs.redis == 'true' - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - # ── fastapi + celery (App/Dockerfile, 같은 버전으로 동시 bump) ────────────── - - name: Bump & build fastapi/celery - if: steps.changes.outputs.app == 'true' - run: | - set -euo pipefail - current=$(grep -oP "seoyunje/deepguard-fastapi:\K[0-9]+\.[0-9]+\.[0-9]+" docker-compose.yml | head -1) - IFS='.' read -r major minor patch <<< "$current" - new_tag="${major}.${minor}.$((patch + 1))" - echo "fastapi/celery: ${current} -> ${new_tag}" - - docker buildx build \ - --target fastapi \ - --tag "${DOCKERHUB_NAMESPACE}/deepguard-fastapi:${new_tag}" \ - --cache-from type=gha,scope=fastapi \ - --cache-to type=gha,mode=max,scope=fastapi \ - --push \ - -f App/Dockerfile . - - docker buildx build \ - --target celery \ - --tag "${DOCKERHUB_NAMESPACE}/deepguard-celery:${new_tag}" \ - --cache-from type=gha,scope=celery \ - --cache-to type=gha,mode=max,scope=celery \ - --push \ - -f App/Dockerfile . - - # ── react (client/Dockerfile) ──────────────────────────────────────────── - - name: Bump & build react - if: steps.changes.outputs.client == 'true' - run: | - set -euo pipefail - current=$(grep -oP "seoyunje/deepguard-react:\K[0-9]+\.[0-9]+\.[0-9]+" docker-compose.yml | head -1) - IFS='.' read -r major minor patch <<< "$current" - new_tag="${major}.${minor}.$((patch + 1))" - echo "react: ${current} -> ${new_tag}" - - docker buildx build \ - --tag "${DOCKERHUB_NAMESPACE}/deepguard-react:${new_tag}" \ - --cache-from type=gha,scope=react \ - --cache-to type=gha,mode=max,scope=react \ - --push \ - -f client/Dockerfile client - - # ── mysql (docker/mysql/Dockerfile) ────────────────────────────────────── - - name: Bump & build mysql - if: steps.changes.outputs.mysql == 'true' - run: | - set -euo pipefail - current=$(grep -oP "seoyunje/deepguard-mysql:\K[0-9]+\.[0-9]+\.[0-9]+" docker-compose.yml | head -1) - IFS='.' read -r major minor patch <<< "$current" - new_tag="${major}.${minor}.$((patch + 1))" - echo "mysql: ${current} -> ${new_tag}" - - docker buildx build \ - --tag "${DOCKERHUB_NAMESPACE}/deepguard-mysql:${new_tag}" \ - --cache-from type=gha,scope=mysql \ - --cache-to type=gha,mode=max,scope=mysql \ - --push \ - -f docker/mysql/Dockerfile . - - # ── redis (docker/redis/Dockerfile) ────────────────────────────────────── - - name: Bump & build redis - if: steps.changes.outputs.redis == 'true' - run: | - set -euo pipefail - current=$(grep -oP "seoyunje/deepguard-redis:\K[0-9]+\.[0-9]+\.[0-9]+" docker-compose.yml | head -1) - IFS='.' read -r major minor patch <<< "$current" - new_tag="${major}.${minor}.$((patch + 1))" - echo "redis: ${current} -> ${new_tag}" - - docker buildx build \ - --tag "${DOCKERHUB_NAMESPACE}/deepguard-redis:${new_tag}" \ - --cache-from type=gha,scope=redis \ - --cache-to type=gha,mode=max,scope=redis \ - --push \ - -f docker/redis/Dockerfile . diff --git a/.github/workflows/docker-bump-push-app.yml b/.github/workflows/docker-bump-push-app.yml new file mode 100644 index 0000000..1d89224 --- /dev/null +++ b/.github/workflows/docker-bump-push-app.yml @@ -0,0 +1,94 @@ +name: Docker Bump & Push - FastAPI/Celery + +on: + push: + branches: [main] + paths: + - "App/**" + - "requirements.txt" + - "deepguard/**" + - "inference/**" + - "explainability/**" + - "preprocess/**" + - "pyproject.toml" + workflow_dispatch: + +env: + DOCKERHUB_NAMESPACE: ${{ secrets.DOCKERHUB_USERNAME }} + GHCR_NAMESPACE: ghcr.io/hanmoonsub + +jobs: + bump-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout + uses: actions/checkout@v7 + with: + lfs: true + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Log in to Docker Hub + uses: docker/login-action@v4 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Log in to GHCR + uses: docker/login-action@v4 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Compute new tag from Docker Hub + id: bump + run: | + set -euo pipefail + + get_latest_tag() { + local repo="$1" + local token tags_json + token=$(curl -s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:${DOCKERHUB_NAMESPACE}/${repo}:pull" | python3 -c "import json,sys;print(json.load(sys.stdin).get('token',''))") + tags_json=$(curl -s -H "Authorization: Bearer ${token}" "https://registry-1.docker.io/v2/${DOCKERHUB_NAMESPACE}/${repo}/tags/list") + echo "$tags_json" | python3 -c "import json,sys; d=json.load(sys.stdin); v=sorted(tuple(int(p) for p in t.split('.')) for t in (d.get('tags') or []) if len(t.split('.'))==3 and all(p.isdigit() for p in t.split('.'))); print('%d.%d.%d'%v[-1] if v else '1.0.0')" + } + + current_fastapi=$(get_latest_tag "deepguard-fastapi") + current_celery=$(get_latest_tag "deepguard-celery") + current=$(printf '%s\n%s\n' "$current_fastapi" "$current_celery" | sort -V | tail -1) + + IFS='.' read -r major minor patch <<< "$current" + new_tag="${major}.${minor}.$((patch + 1))" + echo "fastapi/celery: 현재 최댓값 ${current} -> ${new_tag}" + echo "new_tag=${new_tag}" >> "$GITHUB_OUTPUT" + + - name: Build & push fastapi + uses: docker/build-push-action@v7 + with: + context: . + file: App/Dockerfile + target: fastapi + tags: | + ${{ env.DOCKERHUB_NAMESPACE }}/deepguard-fastapi:${{ steps.bump.outputs.new_tag }} + ${{ env.GHCR_NAMESPACE }}/deepguard-fastapi:${{ steps.bump.outputs.new_tag }} + push: true + cache-from: type=gha,scope=fastapi + cache-to: type=gha,mode=max,scope=fastapi + + - name: Build & push celery + uses: docker/build-push-action@v7 + with: + context: . + file: App/Dockerfile + target: celery + tags: | + ${{ env.DOCKERHUB_NAMESPACE }}/deepguard-celery:${{ steps.bump.outputs.new_tag }} + ${{ env.GHCR_NAMESPACE }}/deepguard-celery:${{ steps.bump.outputs.new_tag }} + push: true + cache-from: type=gha,scope=celery + cache-to: type=gha,mode=max,scope=celery diff --git a/.github/workflows/docker-bump-push-mysql.yml b/.github/workflows/docker-bump-push-mysql.yml new file mode 100644 index 0000000..afa337a --- /dev/null +++ b/.github/workflows/docker-bump-push-mysql.yml @@ -0,0 +1,70 @@ +name: Docker Bump & Push - MySQL + +on: + push: + branches: [main] + paths: + - "docker/mysql/**" + - "App/sql/**" + workflow_dispatch: + +env: + DOCKERHUB_NAMESPACE: ${{ secrets.DOCKERHUB_USERNAME }} + GHCR_NAMESPACE: ghcr.io/hanmoonsub + +jobs: + bump-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout + uses: actions/checkout@v7 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Log in to Docker Hub + uses: docker/login-action@v4 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Log in to GHCR + uses: docker/login-action@v4 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Compute new tag from Docker Hub + id: bump + run: | + set -euo pipefail + + get_latest_tag() { + local repo="$1" + local token tags_json + token=$(curl -s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:${DOCKERHUB_NAMESPACE}/${repo}:pull" | python3 -c "import json,sys;print(json.load(sys.stdin).get('token',''))") + tags_json=$(curl -s -H "Authorization: Bearer ${token}" "https://registry-1.docker.io/v2/${DOCKERHUB_NAMESPACE}/${repo}/tags/list") + echo "$tags_json" | python3 -c "import json,sys; d=json.load(sys.stdin); v=sorted(tuple(int(p) for p in t.split('.')) for t in (d.get('tags') or []) if len(t.split('.'))==3 and all(p.isdigit() for p in t.split('.'))); print('%d.%d.%d'%v[-1] if v else '1.0.0')" + } + + current=$(get_latest_tag "deepguard-mysql") + IFS='.' read -r major minor patch <<< "$current" + new_tag="${major}.${minor}.$((patch + 1))" + echo "mysql: 현재 최댓값 ${current} -> ${new_tag}" + echo "new_tag=${new_tag}" >> "$GITHUB_OUTPUT" + + - name: Build & push mysql + uses: docker/build-push-action@v7 + with: + context: . + file: docker/mysql/Dockerfile + tags: | + ${{ env.DOCKERHUB_NAMESPACE }}/deepguard-mysql:${{ steps.bump.outputs.new_tag }} + ${{ env.GHCR_NAMESPACE }}/deepguard-mysql:${{ steps.bump.outputs.new_tag }} + push: true + cache-from: type=gha,scope=mysql + cache-to: type=gha,mode=max,scope=mysql diff --git a/.github/workflows/docker-bump-push-react.yml b/.github/workflows/docker-bump-push-react.yml new file mode 100644 index 0000000..c17d66d --- /dev/null +++ b/.github/workflows/docker-bump-push-react.yml @@ -0,0 +1,69 @@ +name: Docker Bump & Push - React + +on: + push: + branches: [main] + paths: + - "client/**" + workflow_dispatch: + +env: + DOCKERHUB_NAMESPACE: ${{ secrets.DOCKERHUB_USERNAME }} + GHCR_NAMESPACE: ghcr.io/hanmoonsub + +jobs: + bump-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout + uses: actions/checkout@v7 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Log in to Docker Hub + uses: docker/login-action@v4 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Log in to GHCR + uses: docker/login-action@v4 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Compute new tag from Docker Hub + id: bump + run: | + set -euo pipefail + + get_latest_tag() { + local repo="$1" + local token tags_json + token=$(curl -s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:${DOCKERHUB_NAMESPACE}/${repo}:pull" | python3 -c "import json,sys;print(json.load(sys.stdin).get('token',''))") + tags_json=$(curl -s -H "Authorization: Bearer ${token}" "https://registry-1.docker.io/v2/${DOCKERHUB_NAMESPACE}/${repo}/tags/list") + echo "$tags_json" | python3 -c "import json,sys; d=json.load(sys.stdin); v=sorted(tuple(int(p) for p in t.split('.')) for t in (d.get('tags') or []) if len(t.split('.'))==3 and all(p.isdigit() for p in t.split('.'))); print('%d.%d.%d'%v[-1] if v else '1.0.0')" + } + + current=$(get_latest_tag "deepguard-react") + IFS='.' read -r major minor patch <<< "$current" + new_tag="${major}.${minor}.$((patch + 1))" + echo "react: 현재 최댓값 ${current} -> ${new_tag}" + echo "new_tag=${new_tag}" >> "$GITHUB_OUTPUT" + + - name: Build & push react + uses: docker/build-push-action@v7 + with: + context: client + file: client/Dockerfile + tags: | + ${{ env.DOCKERHUB_NAMESPACE }}/deepguard-react:${{ steps.bump.outputs.new_tag }} + ${{ env.GHCR_NAMESPACE }}/deepguard-react:${{ steps.bump.outputs.new_tag }} + push: true + cache-from: type=gha,scope=react + cache-to: type=gha,mode=max,scope=react diff --git a/.github/workflows/docker-bump-push-redis.yml b/.github/workflows/docker-bump-push-redis.yml new file mode 100644 index 0000000..1bfd5ef --- /dev/null +++ b/.github/workflows/docker-bump-push-redis.yml @@ -0,0 +1,69 @@ +name: Docker Bump & Push - Redis + +on: + push: + branches: [main] + paths: + - "docker/redis/**" + workflow_dispatch: + +env: + DOCKERHUB_NAMESPACE: ${{ secrets.DOCKERHUB_USERNAME }} + GHCR_NAMESPACE: ghcr.io/hanmoonsub + +jobs: + bump-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout + uses: actions/checkout@v7 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Log in to Docker Hub + uses: docker/login-action@v4 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Log in to GHCR + uses: docker/login-action@v4 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Compute new tag from Docker Hub + id: bump + run: | + set -euo pipefail + + get_latest_tag() { + local repo="$1" + local token tags_json + token=$(curl -s "https://auth.docker.io/token?service=registry.docker.io&scope=repository:${DOCKERHUB_NAMESPACE}/${repo}:pull" | python3 -c "import json,sys;print(json.load(sys.stdin).get('token',''))") + tags_json=$(curl -s -H "Authorization: Bearer ${token}" "https://registry-1.docker.io/v2/${DOCKERHUB_NAMESPACE}/${repo}/tags/list") + echo "$tags_json" | python3 -c "import json,sys; d=json.load(sys.stdin); v=sorted(tuple(int(p) for p in t.split('.')) for t in (d.get('tags') or []) if len(t.split('.'))==3 and all(p.isdigit() for p in t.split('.'))); print('%d.%d.%d'%v[-1] if v else '1.0.0')" + } + + current=$(get_latest_tag "deepguard-redis") + IFS='.' read -r major minor patch <<< "$current" + new_tag="${major}.${minor}.$((patch + 1))" + echo "redis: 현재 최댓값 ${current} -> ${new_tag}" + echo "new_tag=${new_tag}" >> "$GITHUB_OUTPUT" + + - name: Build & push redis + uses: docker/build-push-action@v7 + with: + context: . + file: docker/redis/Dockerfile + tags: | + ${{ env.DOCKERHUB_NAMESPACE }}/deepguard-redis:${{ steps.bump.outputs.new_tag }} + ${{ env.GHCR_NAMESPACE }}/deepguard-redis:${{ steps.bump.outputs.new_tag }} + push: true + cache-from: type=gha,scope=redis + cache-to: type=gha,mode=max,scope=redis diff --git a/.github/workflows/first-interaction.yml b/.github/workflows/first-interaction.yml new file mode 100644 index 0000000..ebb3b88 --- /dev/null +++ b/.github/workflows/first-interaction.yml @@ -0,0 +1,27 @@ +name: First interaction + +# 처음 이슈/PR을 남기는 기여자에게 자동으로 환영 댓글을 남긴다. + +on: + issues: + types: [opened] + pull_request_target: + types: [opened] + +permissions: + issues: write + pull-requests: write + +jobs: + greeting: + runs-on: ubuntu-latest + steps: + - uses: actions/first-interaction@v3.1.0 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + issue_message: > + 이슈를 남겨주셔서 감사합니다. 첫 이슈네요. + 메인테이너가 확인 후 곧 답변드리겠습니다. + pr_message: > + PR을 열어주셔서 감사합니다. 첫 PR이네요. + 리뷰 후 피드백 남기겠습니다. diff --git a/.github/workflows/lock-threads.yml b/.github/workflows/lock-threads.yml new file mode 100644 index 0000000..e8aa43a --- /dev/null +++ b/.github/workflows/lock-threads.yml @@ -0,0 +1,30 @@ +name: Lock Threads + +# 오래전에 closed된 이슈/PR을 자동으로 잠가서, 관련 없는 새 댓글(necro-posting)을 방지한다. + +on: + schedule: + - cron: "0 1 * * *" # 매일 UTC 01:00 (KST 10:00) 실행 + workflow_dispatch: + +permissions: + issues: write + pull-requests: write + +jobs: + lock: + runs-on: ubuntu-latest + steps: + - uses: dessant/lock-threads@v6.0.2 + with: + process-only: "issues, prs" + issue-inactive-days: "365" + pr-inactive-days: "365" + issue-comment: > + 이 이슈는 closed된 지 오래되어 자동으로 잠겼습니다. + 관련된 새 이슈가 있다면 새로 열어주세요. + pr-comment: > + 이 PR은 closed된 지 오래되어 자동으로 잠겼습니다. + 관련된 새 PR이 있다면 새로 열어주세요. + issue-lock-reason: "resolved" + pr-lock-reason: "resolved" diff --git a/.github/workflows/pypi-publish.yml b/.github/workflows/pypi-publish.yml new file mode 100644 index 0000000..2903c78 --- /dev/null +++ b/.github/workflows/pypi-publish.yml @@ -0,0 +1,42 @@ +name: Publish to PyPI + +# main에 pyproject.toml이 push되면: README 이미지 경로를 절대 URL로 치환 -> 빌드 -> PyPI에 바로 배포. + +on: + push: + branches: [main] + paths: + - "pyproject.toml" + workflow_dispatch: + +permissions: + contents: read + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + id-token: write # PyPI Trusted Publishing(OIDC)에 필요 - API 토큰 불필요 + steps: + - name: Checkout + uses: actions/checkout@v7 + with: + lfs: true + + - name: Set up Python + uses: actions/setup-python@v7 + with: + python-version: "3.11" + cache: "pip" + + - name: Rewrite relative image paths for PyPI + run: sed -i -E 's#src="docs/#src="https://raw.githubusercontent.com/HanMoonSub/DeepGuard/main/docs/#g' README.md + + - name: Install build tool + run: pip install build + + - name: Build sdist & wheel + run: python -m build + + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 0000000..fac62e4 --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,33 @@ +name: Close Stale Issues + +# 일정 기간 활동 없는 이슈/PR에 stale 라벨을 붙이고, 그 후에도 방치되면 자동으로 닫는다. + +on: + schedule: + - cron: "0 0 * * *" # 매일 UTC 00:00 (KST 09:00) 실행 + workflow_dispatch: + +permissions: + issues: write + pull-requests: write + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v11 + with: + days-before-stale: 60 + days-before-close: 7 + stale-issue-label: "stale" + stale-pr-label: "stale" + stale-issue-message: > + 이 이슈는 60일 동안 활동이 없어 stale 라벨이 추가되었습니다. + 7일 내에 추가 활동이 없으면 자동으로 닫힙니다. + stale-pr-message: > + 이 PR은 60일 동안 활동이 없어 stale 라벨이 추가되었습니다. + 7일 내에 추가 활동이 없으면 자동으로 닫힙니다. + close-issue-message: "60일 이상 활동이 없어 자동으로 닫습니다. 필요하면 다시 열어주세요." + close-pr-message: "60일 이상 활동이 없어 자동으로 닫습니다. 필요하면 다시 열어주세요." + exempt-issue-labels: "pinned,security" + exempt-pr-labels: "pinned" diff --git a/README.md b/README.md index 47997df..8320b37 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Downloads Last Commit Status - Release + Release Repo Size

@@ -28,48 +28,111 @@ W&B

+

+ Docker Ready + Docker Pulls + Docker Version +

+

🇰🇷 한국어 버전 | 🇯🇵 日本語版 | 📈 Model Evaluation | - 🔮 Try Demo + 🤗 Try Demo | + 🤗 Hugging Face

## 📌 Contents -- [💡 Install & Requirements](#-install--requirements) -- [🛠 SetUp](#-setup) +- [🐳 Docker Quick Start](#-docker-quick-start) - Run the full stack (MySQL, Redis, FastAPI, Celery, React) with Docker Compose +- [🤗 Try It Live: Hugging Face Spaces](#-try-it-live-hugging-face-spaces) - No-install browser demos for image, video, and XAI deepfake detection - [📚 DeepFake Video BenchMark Datasets](#-deepfake-video-benchmark-datasets) — Overview of Celeb-DF-v2, FF++, and KoDF datasets used for training. - [⚙️ Data Preparation](#data-preparation) — Efficient face detection and landmark extraction pipeline using YOLOv8 - [🏗 Model Architecture](#-model-architecture) — Detailed look into our hybrid CNN-ViT (MS-EffViT & MS-EffGCViT) designs. - [🧬 Model Zoo](#-model-zoo) — Comparison of model variants, parameter counts, and computational complexity (FLOPs). - [🚀 Training](#-training) - Step-by-step training scrips with Goolge Colab and W&B experiment tracking - [📈 Model Evaluation](#-model-evaluation) - Benchmarking results -- [💻 Model Usage](#-model-usage) - How to integrate DeepGuard models into your own Python code or via timm +- [💻 Model Usage](#-model-usage) - Load pretrained models via `pip install deepguard` or straight from the Hugging Face Hub - [🔮 Predict Image & Video](#-predict-image--video) - Simple Inference examples for detecting deepfakes in image and video - [🎨 DeepFake AI Explainability](#-deepfake-ai-explainability) - Visualizing model focus using Grad-CAM and attention maps - [📓 Tutorials](#-tutorials) - Hands-on Colab notebooks for inference and dual-branch XAI visualization -- [📬 Authors](#-authors) -- [📝 Reference](#-reference) -- [⚖️ License](#-license) +- [📬 Authors](#-authors) - Team behind this senior graduation project at Chungbuk National University +- [📝 Reference](#-reference) - Libraries, datasets, and prior work this project builds on +- [⚖️ License](#-license) - MIT license -## 💡 Install & Requirements +## 🐳 Docker Quick Start -To install requirements: +Run the full stack (MySQL + Redis + FastAPI + Celery + React) with Docker Compose — no local Python/Node setup required. -```python -pip install -r requirements.txt -``` +| **FastAPI** | **Celery** | **Redis** | **MySQL** | **React** | +| --- | --- | --- | --- | --- | +| REST API backend — routes, inference/explain services, DB access
[`seoyunje/deepguard-fastapi`](https://hub.docker.com/r/seoyunje/deepguard-fastapi) | Background worker for async inference, explainability, and cleanup tasks
[`seoyunje/deepguard-celery`](https://hub.docker.com/r/seoyunje/deepguard-celery) | Celery broker/result backend and session store
[`seoyunje/deepguard-redis`](https://hub.docker.com/r/seoyunje/deepguard-redis) | Primary relational database (users, analyses, etc.)
[`seoyunje/deepguard-mysql`](https://hub.docker.com/r/seoyunje/deepguard-mysql) | Web frontend, served on port `80`
[`seoyunje/deepguard-react`](https://hub.docker.com/r/seoyunje/deepguard-react) | -## 🛠 SetUp +**Prerequisites**: [Docker](https://www.docker.com/) with Compose v2 -Clone the repository and move into it: -``` +```bash git clone https://github.com/HanMoonSub/DeepGuard.git - cd DeepGuard +docker compose up -d ``` +Once all containers are up, open **http://localhost:80** in your browser. Images are also mirrored to [GitHub Packages](https://github.com/HanMoonSub/DeepGuard/pkgs/container/deepguard-fastapi). + +

+ DeepGuard Docker Compose architecture +

+ +## 🤗 Try It Live: Hugging Face Spaces + +No install, no GPU, no `docker compose up` — just click and try DeepGuard straight from your browser. + + + + + + + +
+
🖼️
+ Image Detection +
+ Upload an image → real / fake probability +

+
+ + Open Image Detection in Spaces + +
+
+
🎬
+ Video Detection +
+ Upload a video → frame-aggregated probability +

+
+ + Open Video Detection in Spaces + +
+
+
🎨
+ Detection XAI +
+ See why — dual-branch Grad-CAM heatmaps +

+
+ + Open Detection XAI in Spaces + +
+
+ +

+ 💛 Enjoying the demos? Please leave a ❤️ like on the Space — it means a lot to us! +
+ Looking for the underlying checkpoints instead of the demo UI? Jump to 🤗 Model Usage → Hugging Face Hub. +

+ ## 📚 DeepFake Video BenchMark Datasets To evaluate the generalization and robustness of our deepfake detection model, we utilize three large-scale, widely recognized benchmark datasets. Each dataset presents unique challenges and covers different types of forgery methods. @@ -167,6 +230,14 @@ We utilizes two distinct types of self-attention to capture both long-range and ## 🚀 Training +These training scripts run against the full repo, not the `pip install deepguard` package. Clone it and install the full dev environment first: + +```bash +git clone https://github.com/HanMoonSub/DeepGuard.git +cd DeepGuard +pip install -r requirements.txt +``` + We provide training scripts for both `ms_eff_vit` and `ms_eff_gcvit`. We recommend using **Google Colab** for free GPU access and **Weightes & Biases(W&B)** for experiment tracking #### 📊 Weight & Biases Experiments @@ -224,20 +295,17 @@ We provide training scripts for both `ms_eff_vit` and `ms_eff_gcvit`. We recomme ## 💻 Model Usage -**Quick Start** -You can load the models directly via the `DeepGuard` package or through the `timm` interface. +Both options load the raw model only — no face detection/cropping is applied. For end-to-end inference on a real image/video file, see [🔮 Predict Image & Video](#-predict-image--video) below. **Available Datasets**: `celeb_df_v2`, `ff++`, `kodf` -**Installation** +### 📦 Via pip (`deepguard` / `timm`) ```bash -# pip install -U git+https://github.com/HanMoonSub/DeepGuard.git pip install deepguard ``` - -**Option A: Direct Import (via DeepGuard)** +**Direct Import (via DeepGuard)** ```python from deepguard import ms_eff_gcvit_b0, ms_eff_gcvit_b5 @@ -246,7 +314,7 @@ model = ms_eff_gcvit_b0(pretrained=True, dataset="celeb_df_v2") model = ms_eff_gcvit_b5(pretrained=True, dataset="ff++") ``` -**Option B: Using timm Interface (via timm)** +**Using timm Interface** ```python import timm @@ -256,19 +324,32 @@ model = timm.create_model("ms_eff_gcvit_b0", pretrained=True, dataset="ff++") model = timm.create_model("ms_eff_gcvit_b5", pretrained=True, dataset="kodf") ``` -**Option C: Hugging Face Hub** +### 🤗 Via Hugging Face Hub -```python -import torch -from huggingface_hub import hf_hub_download -from deepguard import ms_eff_gcvit_b0 # or ms_eff_gcvit_b5 +Every checkpoint is also mirrored to the [Hugging Face Hub under `KoreaPeter`](https://huggingface.co/KoreaPeter) as its own `transformers`-compatible repo (config + custom modeling code + `safetensors` weights) — usable directly via the `transformers` `pipeline` API with `trust_remote_code=True`, no `deepguard` install required. + +> 💛 Find a checkpoint useful? Please leave a ❤️ like on its model card — it means a lot to us! -REPO_ID = "KoreaPeter/ms-eff-gcvit-deepfake" +```python +from transformers import pipeline -ckpt = hf_hub_download(REPO_ID, "ms_eff_gcvit_b0_kodf.bin") # celeb_df_v2 | ff++ | kodf -model = ms_eff_gcvit_b0(pretrained=False) -model.load_state_dict(torch.load(ckpt, map_location="cpu")) -model.eval() +# 🖼️ Image classification +clf = pipeline( + "image-classification", + model="KoreaPeter/ms-eff-gcvit-deepfake-b0-kodf", # swap for any model card above + trust_remote_code=True, +) +result = clf("face.jpg") +# [{'label': 'fake', 'score': 0.9712}, {'label': 'real', 'score': 0.0288}] + +# 🎬 Video classification +clf = pipeline( + "video-classification", + model="KoreaPeter/ms-eff-gcvit-deepfake-b0-kodf", + trust_remote_code=True, +) +result = clf("video.mp4", num_frames=20, agg_mode="conf") +# [{'label': 'fake', 'score': 0.9634}, {'label': 'real', 'score': 0.0366}] ``` ## 🔮 Predict Image & Video @@ -362,6 +443,10 @@ Each method is assigned to the branch where it performs best empirically. ### 💡 DeepFake XAI Usage +```bash +pip install deepguard +``` + **Low-Level Branch — Local Artifact Detection** ```python @@ -484,24 +569,31 @@ The jupyter notebooks themselves can be found under the tutorials folder in the ## 📬 Authors -_**This project was developed as a Senior Graduation Project by the Department of Software at Chungbuk National University (CBNU), Republic of Korea.**_ +

Senior Graduation Project — Department of Software, Chungbuk National University (CBNU), Republic of Korea

+ +
+ +| Member | Role | Focus | Contact | +| :---: | :--- | :--- | :---: | +| **한문섭** | Data & Backend Engineering | Data Preprocessing Pipeline, DB Schema Design | [✉️](mailto:hanmoon3054@gmail.com) | +| **이예솔** | UI/UX & Frontend Engineering | UI/UX Design, User Dashboard, Model Visualization | [✉️](mailto:yesol4138@chungbuk.ac.kr) | +| **서윤제** | AI Engineering | AI Model Architecture, Inference API Design, Model Serving | [✉️](mailto:seoyunje2001@gmail.com) | -* **한문섭**: **Data & Backend Engineering** (Data Preprocessing Pipeline, DB Schema Design) — [hanmoon3054@gmail.com](mailto:hanmoon3054@gmail.com) -* **이예솔**: **UI/UX & Frontend Engineering** (UI/UX Design, User Dashboard, Model Visualization) — [yesol4138@chungbuk.ac.kr](mailto:yesol4138@chungbuk.ac.kr) -* **서윤제**: **AI Engineering** (AI Model Architecture, Inference API Design, Model Serving) — [seoyunje2001@gmail.com](mailto:seoyunje2001@gmail.com) +
## 📝 Reference -1. [`facenet-pytorch`](https://github.com/timesler/facenet-pytorch) - _Pretrained Face Detection(MTCNN) and Recognition(InceptionResNet) Models by Tim Esler_ -2. [`face-cutout`](https://github.com/sowmen/face-cutout) - _Face Cutout Library by Sowmen_ -3. [`Celeb-DF++`](https://github.com/OUC-VAS/Celeb-DF-PP) - _Celeb-DF++ Dataset by OUC-VAS Group_ -4. [`DeeperForensics-1.0`](https://github.com/EndlessSora/DeeperForensics-1.0) - _DeeperForensics-1.0 Dataset by Endless Sora_ -5. [`Deepfake Detection`](https://github.com/abhijithjadhav/Deepfake_detection_using_deep_learning) - _Detection of Video Deepfake using ResNext and LSTM by Abhijith Jadhav_ -6. [`deepfake-detection-project-v4`](https://github.com/ameencaslam/deepfake-detection-project-v4) - _Multiple Deep Learning Models by Ameen Caslam_ -7. [`Awesome-Deepfake-Detection`](https://github.com/Daisy-Zhang/Awesome-Deepfakes-Detection -) - _A curated list of tools, papers and code by Daisy Zhang_ -8. [`Pytorch-Grad-Cam`](https://github.com/jacobgil/pytorch-grad-cam) - _Advanced Visual Explanations for PyTorch Models_ +| # | Project | Description | +| :---: | --- | --- | +| 1 | [`facenet-pytorch`](https://github.com/timesler/facenet-pytorch) | Pretrained Face Detection (MTCNN) and Recognition (InceptionResNet) Models by Tim Esler | +| 2 | [`face-cutout`](https://github.com/sowmen/face-cutout) | Face Cutout Library by Sowmen | +| 3 | [`Celeb-DF++`](https://github.com/OUC-VAS/Celeb-DF-PP) | Celeb-DF++ Dataset by OUC-VAS Group | +| 4 | [`DeeperForensics-1.0`](https://github.com/EndlessSora/DeeperForensics-1.0) | DeeperForensics-1.0 Dataset by Endless Sora | +| 5 | [`Deepfake Detection`](https://github.com/abhijithjadhav/Deepfake_detection_using_deep_learning) | Detection of Video Deepfake using ResNext and LSTM by Abhijith Jadhav | +| 6 | [`deepfake-detection-project-v4`](https://github.com/ameencaslam/deepfake-detection-project-v4) | Multiple Deep Learning Models by Ameen Caslam | +| 7 | [`Awesome-Deepfake-Detection`](https://github.com/Daisy-Zhang/Awesome-Deepfakes-Detection) | A curated list of tools, papers and code by Daisy Zhang | +| 8 | [`Pytorch-Grad-Cam`](https://github.com/jacobgil/pytorch-grad-cam) | Advanced Visual Explanations for PyTorch Models | ## ⚖️ License diff --git a/README_JP.md b/README_JP.md index 581d6fb..882bb36 100644 --- a/README_JP.md +++ b/README_JP.md @@ -6,7 +6,7 @@ Downloads Last Commit Status - Release + Release Repo Size

@@ -28,49 +28,115 @@ W&B

+

+ Docker Ready + Docker Pulls + Docker Version +

+

🇺🇸 English Version | 🇰🇷 한국어 버전 | 📈 モデル評価 | - 🔮 デモ実行 + 🤗 デモを試す | + 🤗 Hugging Face

## 📌 目次 -- [💡 インストールと要件](#-インストールと要件) -- [🛠 セットアップ](#-セットアップ) +- [🐳 Docker Quick Start](#-docker-quick-start) - Docker Compose でフルスタック(MySQL, Redis, FastAPI, Celery, React)を起動 +- [🤗 今すぐ体験: Hugging Face Spaces](#-今すぐ体験-hugging-face-spaces) - インストール不要、ブラウザだけで試せる画像/動画/XAI ディープフェイク検出デモ - [📚 ディープフェイク動画ベンチマークデータセット](#-ディープフェイク動画ベンチマークデータセット) — 学習に使用した Celeb-DF-v2, FF++, KoDF データセットの概要。 - [⚙️ データ準備](#データ準備) — YOLOv8 を用いた効率的な顔検出およびランドマーク抽出パイプライン。 - [🏗 モデルアーキテクチャ](#-モデルアーキテクチャ) — ハイブリッド CNN-ViT (MS-EffViT & MS-EffGCViT) 設計の詳細。 - [🧬 Model Zoo](#-model-zoo) — モデルバリアントごとのパラメータ数および演算量(FLOPs)の比較。 - [🚀 学習](#-学習) - Google Colab および W&B を活用した段階的な学習スクリプト。 - [📈 モデル評価](#-モデル評価) - ベンチマーク結果。 -- [💻 モデルの使い方](#-モデルの使い方) - Python コードおよび timm を通じた DeepGuard モデルの統合方法。 +- [💻 モデルの使い方](#-モデルの使い方) - `pip install deepguard` または Hugging Face Hub から学習済みモデルをロード - [🔮 画像と動画の予測](#-画像と動画の予測) - ディープフェイク検出のためのシンプルな推論例。 - [🎨 ディープフェイクAI説明可能性(XAI)](#-ディープフェイクai説明可能性xai) - Grad-CAM およびアテンションマップによるモデル判断根拠の可視化。 - [📓 Tutorials](#-tutorials) - 推論とデュアルブランチXAI可視化のためのハンズオンノートブック -- [📬 制作者](#-制作者) -- [📝 参考文献](#-参考文献) -- [⚖️ ライセンス](#-ライセンス) +- [📬 制作者](#-制作者) - 忠北大学校の卒業制作を手がけたチーム紹介 +- [📝 参考文献](#-参考文献) - 本プロジェクトが参考にしたライブラリ、データセット、先行研究 +- [⚖️ ライセンス](#-ライセンス) - MIT ライセンス --- -## 💡 インストールと要件 +## 🐳 Docker Quick Start -必要なライブラリのインストール: +Docker Compose でフルスタック(MySQL + Redis + FastAPI + Celery + React)を起動します — ローカルに Python/Node 環境を用意する必要はありません。 -```bash -pip install -r requirements.txt -``` +| **FastAPI** | **Celery** | **Redis** | **MySQL** | **React** | +| --- | --- | --- | --- | --- | +| REST API バックエンド — ルーティング、推論/説明サービス、DBアクセス
[`seoyunje/deepguard-fastapi`](https://hub.docker.com/r/seoyunje/deepguard-fastapi) | 非同期の推論・説明可能性(XAI)・クリーンアップ処理を行うバックグラウンドワーカー
[`seoyunje/deepguard-celery`](https://hub.docker.com/r/seoyunje/deepguard-celery) | Celery のブローカー/結果バックエンド兼セッションストア
[`seoyunje/deepguard-redis`](https://hub.docker.com/r/seoyunje/deepguard-redis) | メインのリレーショナルデータベース(ユーザー、解析結果など)
[`seoyunje/deepguard-mysql`](https://hub.docker.com/r/seoyunje/deepguard-mysql) | Webフロントエンド、`80` 番ポートで配信
[`seoyunje/deepguard-react`](https://hub.docker.com/r/seoyunje/deepguard-react) | -## 🛠 セットアップ +**前提条件**: Compose v2 を含む [Docker](https://www.docker.com/) -リポジトリをクローンし、該当ディレクトリへ移動します: ```bash git clone https://github.com/HanMoonSub/DeepGuard.git cd DeepGuard +docker compose up -d ``` +すべてのコンテナが起動したら、ブラウザで **http://localhost:80** にアクセスしてください。 + +イメージは Docker Hub の [`seoyunje/deepguard-*`](https://hub.docker.com/u/seoyunje) (`fastapi`, `celery`, `mysql`, `redis`, `react`) として公開されており、[GitHub Packages](https://github.com/HanMoonSub/DeepGuard/pkgs/container/deepguard-fastapi) にもミラーされています。 + +

+ DeepGuard Docker Compose アーキテクチャ +

+ +## 🤗 今すぐ体験: Hugging Face Spaces + +インストールも GPU も `docker compose up` も不要 — ブラウザだけで DeepGuard をすぐに試せます。 + + + + + + + +
+
🖼️
+ 画像検出 +
+ 画像をアップロード → real / fake の確率 +

+
+ + Open Image Detection in Spaces + +
+
+
🎬
+ 動画検出 +
+ 動画をアップロード → フレーム集約による確率 +

+
+ + Open Video Detection in Spaces + +
+
+
🎨
+ 検出XAI +
+ 理由を可視化 — デュアルブランチ Grad-CAM ヒートマップ +

+
+ + Open Detection XAI in Spaces + +
+
+ +

+ 💛 デモが気に入りましたか? Space に ❤️ いいねをお願いします — とても励みになります! +
+ デモUIではなく実際のチェックポイントをお探しですか? 🤗 モデルの使い方 → Hugging Face Hub へどうぞ。 +

+ ## 📚 ディープフェイク動画ベンチマークデータセット モデルの汎化性能と頑健性を評価するため、広く認知された3つの大規模ベンチマークデータセットを使用します。各データセットはそれぞれ異なる改ざん手法と難易度の高い課題を含んでいます。 @@ -162,6 +228,14 @@ DATA_ROOT/ ## 🚀 学習 +これらの学習スクリプトは `pip install deepguard` パッケージではなく、リポジトリ全体を対象に動作します。まずリポジトリをクローンし、フル開発環境をインストールしてください: + +```bash +git clone https://github.com/HanMoonSub/DeepGuard.git +cd DeepGuard +pip install -r requirements.txt +``` + `ms_eff_vit` と `ms_eff_gcvit` の両方について学習スクリプトを提供します。無料の GPU 環境として **Google Colab** を、実験の記録およびトラッキングとして **Weights & Biases(W&B)** の使用を推奨します。 #### 📊 Weight & Biases 実験結果 @@ -218,20 +292,17 @@ DATA_ROOT/ ## 💻 モデルの使い方 -**クイックスタート** -`DeepGuard` パッケージを直接インポートするか、`timm` インターフェースを通じてモデルをロードできます。 +どちらの方法も、顔検出/クロップなどの前処理を行わずモデル単体をロードします。実際の画像/動画ファイルに対するエンドツーエンドの推論は、下記の [🔮 画像と動画の予測](#-画像と動画の予測) を参照してください。 **対応データセット**: `celeb_df_v2`, `ff++`, `kodf` -**インストール** +### 📦 pip で使う (`deepguard` / `timm`) ```bash -# pip install -U git+https://github.com/HanMoonSub/DeepGuard.git pip install deepguard ``` - -**方法 A: 直接インポート (DeepGuard 使用)** +**直接インポート (DeepGuard 使用)** ```python from deepguard import ms_eff_gcvit_b0, ms_eff_gcvit_b5 @@ -240,7 +311,7 @@ model = ms_eff_gcvit_b0(pretrained=True, dataset="celeb_df_v2") model = ms_eff_gcvit_b5(pretrained=True, dataset="ff++") ``` -**方法 B: timm インターフェース使用** +**timm インターフェース使用** ```python import timm @@ -250,19 +321,32 @@ model = timm.create_model("ms_eff_gcvit_b0", pretrained=True, dataset="ff++") model = timm.create_model("ms_eff_gcvit_b5", pretrained=True, dataset="kodf") ``` -**方法 C: Hugging Face Hub** +### 🤗 Hugging Face Hub で使う -```python -import torch -from huggingface_hub import hf_hub_download -from deepguard import ms_eff_gcvit_b0 # or ms_eff_gcvit_b5 +すべてのチェックポイントは [Hugging Face Hub の `KoreaPeter`](https://huggingface.co/KoreaPeter) アカウントにも、`transformers` 互換リポジトリ(設定 + カスタムモデリングコード + `safetensors` の重み)としてミラーされています — `deepguard` をインストールせずに、`trust_remote_code=True` を指定した `transformers` の `pipeline` API から直接利用できます。 + +> 💛 チェックポイントが役に立ったら、モデルカードに ❤️ いいねをお願いします — とても励みになります! -REPO_ID = "KoreaPeter/ms-eff-gcvit-deepfake" +```python +from transformers import pipeline -ckpt = hf_hub_download(REPO_ID, "ms_eff_gcvit_b0_kodf.bin") # celeb_df_v2 | ff++ | kodf -model = ms_eff_gcvit_b0(pretrained=False) -model.load_state_dict(torch.load(ckpt, map_location="cpu")) -model.eval() +# 🖼️ 画像分類 +clf = pipeline( + "image-classification", + model="KoreaPeter/ms-eff-gcvit-deepfake-b0-kodf", # 好きなチェックポイントに置き換え可能 + trust_remote_code=True, +) +result = clf("face.jpg") +# [{'label': 'fake', 'score': 0.9712}, {'label': 'real', 'score': 0.0288}] + +# 🎬 動画分類 +clf = pipeline( + "video-classification", + model="KoreaPeter/ms-eff-gcvit-deepfake-b0-kodf", + trust_remote_code=True, +) +result = clf("video.mp4", num_frames=20, agg_mode="conf") +# [{'label': 'fake', 'score': 0.9634}, {'label': 'real', 'score': 0.0366}] ``` ## 🔮 画像と動画の予測 @@ -351,6 +435,10 @@ print(f"ディープフェイク確率: {result:.4f}") ### 💡 ディープフェイク XAI の使い方 +```bash +pip install deepguard +``` + **Low-Level ブランチ — 局所的アーティファクト検出** ```python @@ -474,24 +562,31 @@ Jupyterノートブックは、gitリポジトリのtutorialsフォルダ内に ## 📬 制作者 -_**本プロジェクトは、忠北大学校(CBNU)ソフトウェア学部の卒業制作(Senior Graduation Project)として開発されました。**_ +

忠北大学校(CBNU)ソフトウェア学部の卒業制作(Senior Graduation Project)

+ +
-* **ハン・ムンソプ(한문섭)**: **Data & Backend Engineering** (データ前処理パイプライン、DBスキーマ設計) — [hanmoon3054@gmail.com](mailto:hanmoon3054@gmail.com) -* **イ・イェソル(이예솔)**: **UI/UX & Frontend Engineering** (UI/UXデザイン、ユーザーダッシュボード、モデル可視化) — [yesol4138@chungbuk.ac.kr](mailto:yesol4138@chungbuk.ac.kr) -* **ソ・ユンジェ(서윤제)**: **AI Engineering** (AIモデルアーキテクチャ設計、推論API設計、モデルサービング) — [seoyunje2001@gmail.com](mailto:seoyunje2001@gmail.com) +| 名前 | 役割 | 担当 | 連絡先 | +| :---: | :--- | :--- | :---: | +| **ハン・ムンソプ(한문섭)** | Data & Backend Engineering | データ前処理パイプライン、DBスキーマ設計 | [✉️](mailto:hanmoon3054@gmail.com) | +| **イ・イェソル(이예솔)** | UI/UX & Frontend Engineering | UI/UXデザイン、ユーザーダッシュボード、モデル可視化 | [✉️](mailto:yesol4138@chungbuk.ac.kr) | +| **ソ・ユンジェ(서윤제)** | AI Engineering | AIモデルアーキテクチャ設計、推論API設計、モデルサービング | [✉️](mailto:seoyunje2001@gmail.com) | +
## 📝 参考文献 -1. [`facenet-pytorch`](https://github.com/timesler/facenet-pytorch) - _Tim Esler による事前学習済み顔検出(MTCNN)および認識(InceptionResNet)モデル_ -2. [`face-cutout`](https://github.com/sowmen/face-cutout) - _Sowmen による Face Cutout ライブラリ_ -3. [`Celeb-DF++`](https://github.com/OUC-VAS/Celeb-DF-PP) - _OUC-VAS Group による Celeb-DF++ データセット_ -4. [`DeeperForensics-1.0`](https://github.com/EndlessSora/DeeperForensics-1.0) - _Endless Sora による DeeperForensics-1.0 データセット_ -5. [`Deepfake Detection`](https://github.com/abhijithjadhav/Deepfake_detection_using_deep_learning) - _Abhijith Jadhav による ResNext と LSTM を用いた動画ディープフェイク検出_ -6. [`deepfake-detection-project-v4`](https://github.com/ameencaslam/deepfake-detection-project-v4) - _Ameen Caslam による複数のディープラーニングモデル_ -7. [`Awesome-Deepfake-Detection`](https://github.com/Daisy-Zhang/Awesome-Deepfakes-Detection) - _Daisy Zhang がまとめたツール・論文・コードのキュレーションリスト_ -8. [`Pytorch-Grad-Cam`](https://github.com/jacobgil/pytorch-grad-cam) - _PyTorch モデルのための高度な視覚的説明ツール_ +| # | プロジェクト | 説明 | +| :---: | --- | --- | +| 1 | [`facenet-pytorch`](https://github.com/timesler/facenet-pytorch) | Tim Esler による事前学習済み顔検出(MTCNN)および認識(InceptionResNet)モデル | +| 2 | [`face-cutout`](https://github.com/sowmen/face-cutout) | Sowmen による Face Cutout ライブラリ | +| 3 | [`Celeb-DF++`](https://github.com/OUC-VAS/Celeb-DF-PP) | OUC-VAS Group による Celeb-DF++ データセット | +| 4 | [`DeeperForensics-1.0`](https://github.com/EndlessSora/DeeperForensics-1.0) | Endless Sora による DeeperForensics-1.0 データセット | +| 5 | [`Deepfake Detection`](https://github.com/abhijithjadhav/Deepfake_detection_using_deep_learning) | Abhijith Jadhav による ResNext と LSTM を用いた動画ディープフェイク検出 | +| 6 | [`deepfake-detection-project-v4`](https://github.com/ameencaslam/deepfake-detection-project-v4) | Ameen Caslam による複数のディープラーニングモデル | +| 7 | [`Awesome-Deepfake-Detection`](https://github.com/Daisy-Zhang/Awesome-Deepfakes-Detection) | Daisy Zhang がまとめたツール・論文・コードのキュレーションリスト | +| 8 | [`Pytorch-Grad-Cam`](https://github.com/jacobgil/pytorch-grad-cam) | PyTorch モデルのための高度な視覚的説明ツール | ## ⚖️ ライセンス -本プロジェクトは MIT ライセンスの条件の下で配布されます。 \ No newline at end of file +本プロジェクトは MIT ライセンスの条件の下で配布されます。 diff --git a/README_KR.md b/README_KR.md index 18d0c38..3f0a846 100644 --- a/README_KR.md +++ b/README_KR.md @@ -6,7 +6,7 @@ Downloads Last Commit Status - Release + Release Repo Size

@@ -28,49 +28,115 @@ W&B

+

+ Docker Ready + Docker Pulls + Docker Version +

+

🇺🇸 English Version | 🇯🇵 日本語版 | 📈 모델 평가 | - 🔮 데모 실행 + 🤗 데모 체험 | + 🤗 Hugging Face

## 📌 목차 -- [💡 설치 및 요구사항](#-설치-및-요구사항) -- [🛠 설정](#-설정) +- [🐳 Docker Quick Start](#-docker-quick-start) - Docker Compose로 전체 스택(MySQL, Redis, FastAPI, Celery, React) 실행 +- [🤗 지금 바로 체험하기: Hugging Face Spaces](#-지금-바로-체험하기-hugging-face-spaces) - 설치 없이 브라우저에서 바로 체험하는 이미지/비디오/XAI 딥페이크 탐지 데모 - [📚 딥페이크 비디오 벤치마크 데이터셋](#-딥페이크-비디오-벤치마크-데이터셋) — 학습에 사용된 Celeb-DF-v2, FF++, KoDF 데이터셋 개요. - [⚙️ 데이터 준비](#데이터-준비) — YOLOv8을 이용한 효율적인 얼굴 검출 및 랜드마크 추출 파이프라인. - [🏗 모델 구조](#-모델-구조) — 하이브리드 CNN-ViT (MS-EffViT & MS-EffGCViT) 설계 상세. - [🧬 모델 주(Model Zoo)](#-model-zoo) — 모델 변체별 파라미터 수 및 연산량(FLOPs) 비교. - [🚀 학습](#-학습) - Google Colab 및 W&B를 활용한 단계별 학습 스크립트. - [📈 모델 평가](#-모델-평가) - 벤치마크 결과. -- [💻 모델 사용법](#-모델-사용법) - Python 코드 및 timm을 통한 DeepGuard 모델 통합 방법. +- [💻 모델 사용법](#-모델-사용법) - `pip install deepguard` 또는 Hugging Face Hub를 통한 사전 학습 모델 로드 - [🔮 이미지 및 비디오 예측](#-이미지-및-비디오-예측) - 딥페이크 탐지를 위한 간단한 추론 예시. - [🎨 딥페이크 AI 설명가능성(XAI)](#-딥페이크-ai-설명가능성xai) - Grad-CAM 및 어텐션 맵을 통한 모델 판단 근거 시각화. - [📓 Tutorials](#-tutorials) - 추론과 듀얼 브랜치 XAI 시각화를 위한 실습 노트북 -- [📬 제작자](#-제작자) -- [📝 참고 문헌](#-참고-문헌) -- [⚖️ 라이선스](#-라이선스) +- [📬 제작자](#-제작자) - 충북대학교 졸업 작품을 만든 팀 소개 +- [📝 참고 문헌](#-참고-문헌) - 이 프로젝트가 참고한 라이브러리, 데이터셋, 선행 연구 +- [⚖️ 라이선스](#-라이선스) - MIT 라이선스 --- -## 💡 설치 및 요구사항 +## 🐳 Docker Quick Start -필수 라이브러리 설치: +Docker Compose로 전체 스택(MySQL + Redis + FastAPI + Celery + React)을 실행합니다 — 로컬에 Python/Node 환경을 따로 설치할 필요가 없습니다. -```bash -pip install -r requirements.txt -``` +| **FastAPI** | **Celery** | **Redis** | **MySQL** | **React** | +| --- | --- | --- | --- | --- | +| REST API 백엔드 — 라우트, 추론/설명 서비스, DB 접근
[`seoyunje/deepguard-fastapi`](https://hub.docker.com/r/seoyunje/deepguard-fastapi) | 비동기 추론, 설명가능성(XAI), 정리 작업을 위한 백그라운드 워커
[`seoyunje/deepguard-celery`](https://hub.docker.com/r/seoyunje/deepguard-celery) | Celery 브로커/결과 저장소 및 세션 스토어
[`seoyunje/deepguard-redis`](https://hub.docker.com/r/seoyunje/deepguard-redis) | 주 관계형 데이터베이스 (사용자, 분석 기록 등)
[`seoyunje/deepguard-mysql`](https://hub.docker.com/r/seoyunje/deepguard-mysql) | 웹 프론트엔드, `80`번 포트로 서빙
[`seoyunje/deepguard-react`](https://hub.docker.com/r/seoyunje/deepguard-react) | -## 🛠 설정 +**사전 요구사항**: Compose v2가 포함된 [Docker](https://www.docker.com/) -저장소를 클론하고 해당 디렉토리로 이동합니다: ```bash git clone https://github.com/HanMoonSub/DeepGuard.git cd DeepGuard +docker compose up -d ``` +모든 컨테이너가 정상적으로 실행되면 브라우저에서 **http://localhost:80**으로 접속하세요. + +이미지는 Docker Hub의 [`seoyunje/deepguard-*`](https://hub.docker.com/u/seoyunje) (`fastapi`, `celery`, `mysql`, `redis`, `react`)에 배포되며, [GitHub Packages](https://github.com/HanMoonSub/DeepGuard/pkgs/container/deepguard-fastapi)에도 미러링됩니다. + +

+ DeepGuard Docker Compose 아키텍처 +

+ +## 🤗 지금 바로 체험하기: Hugging Face Spaces + +설치도, GPU도, `docker compose up`도 필요 없습니다 — 브라우저에서 바로 DeepGuard를 체험해보세요. + + + + + + + +
+
🖼️
+ 이미지 탐지 +
+ 이미지를 업로드하면 → real / fake 확률 +

+
+ + Open Image Detection in Spaces + +
+
+
🎬
+ 비디오 탐지 +
+ 비디오를 업로드하면 → 프레임 집계 확률 +

+
+ + Open Video Detection in Spaces + +
+
+
🎨
+ 탐지 XAI +
+ 왜 그렇게 판단했는지 확인 — 듀얼 브랜치 Grad-CAM 히트맵 +

+
+ + Open Detection XAI in Spaces + +
+
+ +

+ 💛 데모가 마음에 드셨나요? Space에 ❤️ 좋아요를 남겨주세요 — 큰 힘이 됩니다! +
+ 데모 UI 대신 실제 체크포인트를 찾고 계신가요? 🤗 모델 사용법 → Hugging Face Hub로 이동하세요. +

+ ## 📚 딥페이크 비디오 벤치마크 데이터셋 모델의 범용성과 강건성을 평가하기 위해 널리 인정받는 세 가지 대규모 벤치마크 데이터셋을 사용합니다. 각 데이터셋은 서로 다른 조작 기법과 도전적인 과제들을 포함하고 있습니다. @@ -162,6 +228,14 @@ DATA_ROOT/ ## 🚀 학습 +이 학습 스크립트는 `pip install deepguard` 패키지가 아니라 리포지토리 전체를 대상으로 동작합니다. 먼저 리포지토리를 클론하고 전체 개발 환경을 설치하세요: + +```bash +git clone https://github.com/HanMoonSub/DeepGuard.git +cd DeepGuard +pip install -r requirements.txt +``` + `ms_eff_vit` 및 `ms_eff_gcvit` 모두에 대한 학습 스크립트를 제공합니다. 무료 GPU 환경을 위해 **Google Colab**을, 실험 기록 및 트래킹을 위해 **Weights & Biases(W&B)** 사용을 권장합니다. #### 📊 Weight & Biases 실험 결과 @@ -218,20 +292,17 @@ DATA_ROOT/ ## 💻 모델 사용법 -**빠른 시작** -`DeepGuard` 패키지를 직접 임포트하거나 `timm` 인터페이스를 통해 모델을 로드할 수 있습니다. +두 방법 모두 얼굴 검출/크롭 같은 전처리 없이 순수 모델만 로드합니다. 실제 이미지/영상 파일에 대한 end-to-end 추론은 아래 [🔮 이미지 및 비디오 예측](#-이미지-및-비디오-예측)을 참고하세요. **지원 데이터셋**: `celeb_df_v2`, `ff++`, `kodf` -**설치** +### 📦 pip으로 사용하기 (`deepguard` / `timm`) ```bash -# pip install -U git+https://github.com/HanMoonSub/DeepGuard.git pip install deepguard ``` - -**방법 A: 직접 임포트 (DeepGuard 사용)** +**직접 임포트 (DeepGuard 사용)** ```python from deepguard import ms_eff_gcvit_b0, ms_eff_gcvit_b5 @@ -240,7 +311,7 @@ model = ms_eff_gcvit_b0(pretrained=True, dataset="celeb_df_v2") model = ms_eff_gcvit_b5(pretrained=True, dataset="ff++") ``` -**방법 B: timm 인터페이스 사용** +**timm 인터페이스 사용** ```python import timm @@ -250,19 +321,32 @@ model = timm.create_model("ms_eff_gcvit_b0", pretrained=True, dataset="ff++") model = timm.create_model("ms_eff_gcvit_b5", pretrained=True, dataset="kodf") ``` -**방법 C: Hugging Face Hub** +### 🤗 Hugging Face Hub로 사용하기 -```python -import torch -from huggingface_hub import hf_hub_download -from deepguard import ms_eff_gcvit_b0 # or ms_eff_gcvit_b5 +모든 체크포인트는 [Hugging Face Hub의 `KoreaPeter`](https://huggingface.co/KoreaPeter) 계정에도 `transformers` 호환 리포(설정 + 커스텀 모델링 코드 + `safetensors` 가중치)로 미러링되어 있습니다 — `deepguard` 설치 없이 `trust_remote_code=True` 옵션의 `transformers` `pipeline` API로 바로 사용할 수 있습니다. + +> 💛 체크포인트가 유용하셨다면 모델 카드에 ❤️ 좋아요를 남겨주세요 — 큰 힘이 됩니다! -REPO_ID = "KoreaPeter/ms-eff-gcvit-deepfake" +```python +from transformers import pipeline -ckpt = hf_hub_download(REPO_ID, "ms_eff_gcvit_b0_kodf.bin") # celeb_df_v2 | ff++ | kodf -model = ms_eff_gcvit_b0(pretrained=False) -model.load_state_dict(torch.load(ckpt, map_location="cpu")) -model.eval() +# 🖼️ 이미지 분류 +clf = pipeline( + "image-classification", + model="KoreaPeter/ms-eff-gcvit-deepfake-b0-kodf", # 원하는 체크포인트로 교체 가능 + trust_remote_code=True, +) +result = clf("face.jpg") +# [{'label': 'fake', 'score': 0.9712}, {'label': 'real', 'score': 0.0288}] + +# 🎬 비디오 분류 +clf = pipeline( + "video-classification", + model="KoreaPeter/ms-eff-gcvit-deepfake-b0-kodf", + trust_remote_code=True, +) +result = clf("video.mp4", num_frames=20, agg_mode="conf") +# [{'label': 'fake', 'score': 0.9634}, {'label': 'real', 'score': 0.0366}] ``` ## 🔮 이미지 및 비디오 예측 @@ -351,6 +435,10 @@ print(f"딥페이크 확률: {result:.4f}") ### 💡 딥페이크 XAI 사용법 +```bash +pip install deepguard +``` + **Low-Level 브랜치 — 국부적 아티팩트 탐지** ```python @@ -474,24 +562,31 @@ result = explainer.display_heatmap_bbox_on_image( ## 📬 제작자 -_**본 프로젝트는 충북대학교(CBNU) 소프트웨어학부 졸업 작품(Senior Graduation Project)으로 개발되었습니다.**_ +

충북대학교(CBNU) 소프트웨어학부 졸업 작품(Senior Graduation Project)

+ +
-* **한문섭**: **Data & Backend Engineering** (데이터 전처리 파이프라인, DB 스키마 설계) — [hanmoon3054@gmail.com](mailto:hanmoon3054@gmail.com) -* **이예솔**: **UI/UX & Frontend Engineering** (UI/UX 디자인, 사용자 대시보드, 모델 시각화) — [yesol4138@chungbuk.ac.kr](mailto:yesol4138@chungbuk.ac.kr) -* **서윤제**: **AI Engineering** (AI 모델 구조 설계, 추론 API 설계, 모델 서빙) — [seoyunje2001@gmail.com](mailto:seoyunje2001@gmail.com) +| 이름 | 역할 | 담당 업무 | 연락처 | +| :---: | :--- | :--- | :---: | +| **한문섭** | Data & Backend Engineering | 데이터 전처리 파이프라인, DB 스키마 설계 | [✉️](mailto:hanmoon3054@gmail.com) | +| **이예솔** | UI/UX & Frontend Engineering | UI/UX 디자인, 사용자 대시보드, 모델 시각화 | [✉️](mailto:yesol4138@chungbuk.ac.kr) | +| **서윤제** | AI Engineering | AI 모델 구조 설계, 추론 API 설계, 모델 서빙 | [✉️](mailto:seoyunje2001@gmail.com) | +
## 📝 참고 문헌 -1. [`facenet-pytorch`](https://github.com/timesler/facenet-pytorch) - _Tim Esler의 사전 학습된 얼굴 검출(MTCNN) 및 인식(InceptionResNet) 모델_ -2. [`face-cutout`](https://github.com/sowmen/face-cutout) - _Sowmen의 Face Cutout 라이브러리_ -3. [`Celeb-DF++`](https://github.com/OUC-VAS/Celeb-DF-PP) - _OUC-VAS Group의 Celeb-DF++ 데이터셋_ -4. [`DeeperForensics-1.0`](https://github.com/EndlessSora/DeeperForensics-1.0) - _Endless Sora의 DeeperForensics-1.0 데이터셋_ -5. [`Deepfake Detection`](https://github.com/abhijithjadhav/Deepfake_detection_using_deep_learning) - _Abhijith Jadhav의 ResNext와 LSTM을 이용한 비디오 딥페이크 탐지_ -6. [`deepfake-detection-project-v4`](https://github.com/ameencaslam/deepfake-detection-project-v4) - _Ameen Caslam의 다중 딥러닝 모델_ -7. [`Awesome-Deepfake-Detection`](https://github.com/Daisy-Zhang/Awesome-Deepfakes-Detection) - _Daisy Zhang이 정리한 도구, 논문, 코드 큐레이션 목록_ -8. [`Pytorch-Grad-Cam`](https://github.com/jacobgil/pytorch-grad-cam) - _PyTorch 모델을 위한 고급 시각적 설명 도구_ +| # | 프로젝트 | 설명 | +| :---: | --- | --- | +| 1 | [`facenet-pytorch`](https://github.com/timesler/facenet-pytorch) | Tim Esler의 사전 학습된 얼굴 검출(MTCNN) 및 인식(InceptionResNet) 모델 | +| 2 | [`face-cutout`](https://github.com/sowmen/face-cutout) | Sowmen의 Face Cutout 라이브러리 | +| 3 | [`Celeb-DF++`](https://github.com/OUC-VAS/Celeb-DF-PP) | OUC-VAS Group의 Celeb-DF++ 데이터셋 | +| 4 | [`DeeperForensics-1.0`](https://github.com/EndlessSora/DeeperForensics-1.0) | Endless Sora의 DeeperForensics-1.0 데이터셋 | +| 5 | [`Deepfake Detection`](https://github.com/abhijithjadhav/Deepfake_detection_using_deep_learning) | Abhijith Jadhav의 ResNext와 LSTM을 이용한 비디오 딥페이크 탐지 | +| 6 | [`deepfake-detection-project-v4`](https://github.com/ameencaslam/deepfake-detection-project-v4) | Ameen Caslam의 다중 딥러닝 모델 | +| 7 | [`Awesome-Deepfake-Detection`](https://github.com/Daisy-Zhang/Awesome-Deepfakes-Detection) | Daisy Zhang이 정리한 도구, 논문, 코드 큐레이션 목록 | +| 8 | [`Pytorch-Grad-Cam`](https://github.com/jacobgil/pytorch-grad-cam) | PyTorch 모델을 위한 고급 시각적 설명 도구 | ## ⚖️ 라이선스 -본 프로젝트는 MIT 라이선스 조건에 따라 배포됩니다. \ No newline at end of file +본 프로젝트는 MIT 라이선스 조건에 따라 배포됩니다. diff --git a/client/Dockerfile b/client/Dockerfile index 67593b3..67aaadf 100644 --- a/client/Dockerfile +++ b/client/Dockerfile @@ -1,4 +1,4 @@ -FROM node:20.18-alpine AS build +FROM node:26.7-alpine AS build WORKDIR /app @@ -9,7 +9,7 @@ COPY . . ENV GENERATE_SOURCEMAP=false RUN npm run build -FROM nginx:1.27-alpine +FROM nginx:1.30-alpine COPY --from=build /app/build /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d/default.conf diff --git a/docker-compose.yml b/docker-compose.yml index 3db6439..cb1c93f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -17,7 +17,7 @@ x-app-env: &app-env services: mysql: - image: seoyunje/deepguard-mysql:1.0.0 + image: seoyunje/deepguard-mysql:1.0.6 container_name: deepguard-mysql networks: [deepguard-network] environment: @@ -29,14 +29,14 @@ services: - deepguard-data:/var/lib/mysql redis: - image: seoyunje/deepguard-redis:1.0.0 + image: seoyunje/deepguard-redis:1.0.6 container_name: deepguard-redis networks: [deepguard-network] volumes: - deepguard-memory:/data fastapi: - image: seoyunje/deepguard-fastapi:1.0.0 + image: seoyunje/deepguard-fastapi:1.0.15 container_name: deepguard-fastapi networks: [deepguard-network] environment: @@ -49,7 +49,7 @@ services: - redis celery: - image: seoyunje/deepguard-celery:1.0.0 + image: seoyunje/deepguard-celery:1.0.15 container_name: deepguard-celery networks: [deepguard-network] environment: @@ -62,7 +62,7 @@ services: - redis react: - image: seoyunje/deepguard-react:1.0.0 + image: seoyunje/deepguard-react:1.0.7 container_name: deepguard-react networks: [deepguard-network] ports: diff --git a/docker/mysql/Dockerfile b/docker/mysql/Dockerfile index 3bcec60..49abf57 100644 --- a/docker/mysql/Dockerfile +++ b/docker/mysql/Dockerfile @@ -1,4 +1,4 @@ -FROM mysql:9.5-oraclelinux9 +FROM mysql:26.7-oraclelinux9 COPY App/sql/*.sql /docker-entrypoint-initdb.d/ diff --git a/docker/redis/Dockerfile b/docker/redis/Dockerfile index 06629f2..40017a1 100644 --- a/docker/redis/Dockerfile +++ b/docker/redis/Dockerfile @@ -1,4 +1,4 @@ -FROM redis:7.4-alpine +FROM redis:8.10-alpine COPY docker/redis/config/redis.conf /usr/local/etc/redis/redis.conf diff --git a/docs/architectures/docker_compose_architecture.png b/docs/architectures/docker_compose_architecture.png new file mode 100644 index 0000000..f6adbf8 Binary files /dev/null and b/docs/architectures/docker_compose_architecture.png differ diff --git a/pyproject.toml b/pyproject.toml index 5f7357f..952eaa8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,13 +8,15 @@ build-backend = "setuptools.build_meta" # ───────────────────────────────────────────── [project] name = "deepguard" # pip install deepguard 할 때 이 이름 -version = "0.3.0" # pip install deepguard==0.2.4 으로 버전 고정 가능 +version = "1.0.0" description = "Multi-Scale Efficient Global Context Vision Transformer for Robust Deepfake Detection" readme = "README.md" # PyPI 페이지에 표시될 설명 (마크다운) -requires-python = ">=3.10" # 이 버전 미만이면 pip install 자체를 막음 +requires-python = ">=3.10" # torch/torchvision/torchmetrics의 Requires-Python 하한이 3.10이라 이 값을 그대로 따름 license = { text = "MIT" } authors = [ - { name = "seoyunje", email = "seoyunje2001@gmail.com" } + { name = "seoyunje", email = "seoyunje2001@gmail.com" }, + { name = "한문섭", email = "hanmoon3054@gmail.com" }, + { name = "이예솔", email = "yesol4138@chungbuk.ac.kr" } ] classifiers = [ "Programming Language :: Python :: 3", @@ -24,17 +26,30 @@ classifiers = [ "Operating System :: OS Independent", "Topic :: Scientific/Engineering :: Artificial Intelligence", ] -dependencies = ["torchmetrics>=1.6.1", - "ultralytics>=8.4.41", - "grad-cam>=1.5.5", - "timm>=1.0.12", - "torch>=2.10.0" - ] +dependencies = [ + "torch>=2.10.0", + "torchmetrics>=1.6.1", + "timm>=1.0.12", + "ultralytics>=8.4.41", + "grad-cam>=1.5.5", + "albumentations>=2.0.8", + "opencv-python>=5.0.0.93", + "numpy>=1.23.0,<3.0.0", + "pandas>=2.2.3", + "scikit-learn>=1.6.1", + "scipy>=1.10.0", + "matplotlib>=3.10.9", + "tqdm>=4.60.0", + "colorama>=0.4.6", +] [project.urls] Homepage = "https://github.com/HanMoonSub/DeepGuard" "Bug Tracker" = "https://github.com/HanMoonSub/DeepGuard/issues" "Source Code" = "https://github.com/HanMoonSub/DeepGuard" -"Hugging Face" = "https://huggingface.co/KoreaPeter/ms-eff-gcvit-deepfake" +"Hugging Face" = "https://huggingface.co/KoreaPeter" +"Demo - DeepFake Image" = "https://huggingface.co/spaces/KoreaPeter/DeepFake-Image-Detection" +"Demo - DeepFake Video" = "https://huggingface.co/spaces/KoreaPeter/DeepFake-Video-Detection" +"Demo - DeepFake XAI" = "https://huggingface.co/spaces/KoreaPeter/DeepFake-Detection-XAI" [tool.setuptools.packages.find] include = [ "deepguard*", # 모델, 레이어, 데이터셋 등 핵심 패키지 diff --git a/requirements.txt b/requirements.txt index e4bb2ea..3df354e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,18 +1,18 @@ # --- [Core Backend & Server] --- -fastapi>=0.135.1 -uvicorn>=0.41.0 -python-multipart>=0.0.22 -pydantic[email]>=2.12.5 +fastapi>=0.141.1 +uvicorn>=0.52.3 +python-multipart>=0.0.32 +pydantic[email]>=2.13.4 aiofiles>=25.1.0 itsdangerous>=2.2.0 -python-dotenv>=0.9.9 +python-dotenv>=1.2.3 # --- [Database & ORM] --- -sqlalchemy>=2.0.48 -pymysql>=1.1.2 +sqlalchemy>=2.0.52 +pymysql>=1.2.0 aiomysql>=0.3.2 -mysql-connector-python>=9.6.0 -redis>=7.4.0 +mysql-connector-python>=26.7.0 +redis>=8.1.0 # --- [Security & Auth] --- bcrypt==4.0.1 # pinned: passlib 1.7.4 breaks on bcrypt>=4.1 (72-byte length check regression) @@ -25,20 +25,20 @@ pandas>=2.2.3 scikit-learn>=1.6.1 # --- [Computer Vision & Image Processing] --- -opencv-python>=4.11.0 -Pillow>=11.1.0 +opencv-python>=5.0.0.93 +Pillow>=12.3.0 albumentations>=2.0.8 # --- [Deep Learning Framework] --- torch>=2.10.0 -torchvision>=0.25.0 +torchvision>=0.28.0 torchmetrics>=1.6.1 timm>=1.0.12 ultralytics>=8.4.41 grad-cam>=1.5.5 # --- [Visualization & Utilities] --- -matplotlib>=3.10.0 +matplotlib>=3.10.9 seaborn>=0.13.2 colorama>=0.4.6 @@ -46,4 +46,4 @@ colorama>=0.4.6 celery>=5.6.3 # --- [Linting & Formatting] --- -ruff>=0.9.0 \ No newline at end of file +ruff>=0.16.3 \ No newline at end of file