Compare commits

...

3 commits

Author SHA1 Message Date
Prunebutt
30ee8107fd finally works...? 2025-10-19 22:31:59 +02:00
Prunebutt
e047bcd136 working with pyproject-nix flake 2025-10-15 21:41:56 +02:00
Prunebutt
bb1b8eecb9 switch to uv and stuff 2025-10-14 00:01:19 +02:00
7 changed files with 278 additions and 62 deletions

11
.gitignore vendored Normal file
View file

@ -0,0 +1,11 @@
# Devenv
.devenv*
devenv.local.nix
devenv.local.yaml
# direnv
.direnv
# pre-commit
.pre-commit-config.yaml
src/protestswap/__pycache__

61
flake.lock generated
View file

@ -1,43 +1,58 @@
{
"nodes": {
"nixpkgs": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1760164275,
"narHash": "sha256-gKl2Gtro/LNf8P+4L3S2RsZ0G390ccd5MyXYrTdMCFE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "362791944032cb532aabbeed7887a441496d5e6e",
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"pyproject-nix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"nixpkgs": {
"locked": {
"lastModified": 1759739877,
"narHash": "sha256-XfcxM4nzSuuRmFGiy/MhGwYf9EennQ2+0jjR2aJqtKE=",
"owner": "pyproject-nix",
"repo": "pyproject.nix",
"rev": "966e0961f9670f847439ba90dc25ffaa112d8803",
"lastModified": 1760284886,
"narHash": "sha256-TK9Kr0BYBQ/1P5kAsnNQhmWWKgmZXwUQr4ZMjCzWf2c=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "cf3f5c4def3c7b5f1fc012b3d839575dbe552d43",
"type": "github"
},
"original": {
"owner": "pyproject-nix",
"repo": "pyproject.nix",
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
"pyproject-nix": "pyproject-nix"
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},

204
flake.nix
View file

@ -1,41 +1,183 @@
{
description = "Flake using pyproject.toml metadata";
inputs.pyproject-nix.url = "github:pyproject-nix/pyproject.nix";
inputs.pyproject-nix.inputs.nixpkgs.follows = "nixpkgs";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
pyproject-nix = {
url = "github:pyproject-nix/pyproject.nix";
inputs.nixpkgs.follows = "nixpkgs";
};
flake-utils.url = "github:numtide/flake-utils";
};
outputs =
{ nixpkgs, pyproject-nix, ... }:
let
inherit (nixpkgs) lib;
forAllSystems = lib.genAttrs lib.systems.flakeExposed;
outputs = {
self,
nixpkgs,
flake-utils,
...
}@inputs: let
system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system};
project = inputs.pyproject-nix.lib.project.loadPyproject {
projectRoot = ./.;
};
projectName = project.pyproject.project.name;
python = pkgs.python3;
project = pyproject-nix.lib.project.loadPyproject {
projectRoot = ./.;
inswapperModel = pkgs.stdenv.mkDerivation {
name = "inswapper_128";
src = pkgs.fetchurl {
url = "https://huggingface.co/thebiglaskowski/inswapper_128.onnx/resolve/main/inswapper_128.onnx";
hash = "sha256-5KPwjHU8ty0E4Qqg99vj3uu/OVZ9Tq1tzgjpiqSeFq8=";
};
pythonAttr = "python3";
in
{
devShells = forAllSystems (system: {
default =
let
pkgs = nixpkgs.legacyPackages.${system};
python = pkgs.${pythonAttr};
pythonEnv = python.withPackages (project.renderers.withPackages { inherit python; });
in
pkgs.mkShell { packages = [ pythonEnv ]; };
});
phases = [ "installPhase" ];
packages = forAllSystems (
system:
let
pkgs = nixpkgs.legacyPackages.${system};
python = pkgs.${pythonAttr};
in
{
default = python.pkgs.buildPythonPackage (project.renderers.buildPythonPackage { inherit python; });
}
);
installPhase = ''
mkdir -p "$out/var/lib/insightface/models/"
cp $src "$out/var/lib/insightface/models/inswapper_128.onnx"
'';
};
buffaloModel = pkgs.stdenv.mkDerivation {
name = "buffalo_l_Model";
src = pkgs.fetchurl {
url = "https://github.com/deepinsight/insightface/releases/download/v0.7/buffalo_l.zip";
hash = "sha256-gP/jfYpZQNWac4TCAaKjjUdB8vPFHu9G67KCGKewyi8=";
};
unpackPhase = /*shell*/''
ls -l $src
echo $src
mkdir -p "$out/var/lib/insightface/buffalo_l/"
unar -D -o $out/var/lib/insightface/buffalo_l/ $src
'';
nativeBuildInputs = [ pkgs.unar ];
};
postInstall = /*shell*/''
mkdir -p $out/var/lib/insightface/models/buffalo_l
cp ${inswapperModel} $out/var/lib/insightface/models/inswapper_128.onnx
'';
# ${pkgs.unar}/bin/unar -D -o $out/var/lib/insightface/models/buffalo_l ${buffaloModel}
# '';
packageAttrs = project.renderers.buildPythonPackage {
inherit python;
};
packageAttrsLive = project.renderers.mkPythonEditablePackage {
inherit python;
};
protestswap = python.pkgs.buildPythonPackage ( packageAttrs # // { inherit postInstall; }
);
in {
devShells.${system}.default = let
arg = project.renderers.mkPythonEditablePackage { inherit python; };
pythonEnv = python.pkgs.mkPythonEditablePackage ( arg );
in pkgs.mkShell {
packages = [ pkgs.python3 pkgs.uv
# buffaloModel
protestswap pkgs.gcc14 ];
shellHook = /*shell*/
''
ls -l ${buffaloModel}
INSIGHTFACE_ROOT_DIR=$(mktemp -d /tmp/insightface.XXXXXXXX)
export INSIGHTFACE_ROOT_DIR
mkdir -p "$INSIGHTFACE_ROOT_DIR"
ln -s ${inswapperModel}/var/lib/insightface/models "$INSIGHTFACE_ROOT_DIR/models"
ln -s ${buffaloModel}/var/lib/insightface/buffalo_l "$INSIGHTFACE_ROOT_DIR/buffalo_l"
# export PROTESTSWAP_ROOT="/tmp/protestswap_models"
# mkdir -p "$PROTESTSWAP_ROOT/buffalo_l"
#
# cp ${inswapperModel} "$PROTESTSWAP_ROOT/inswapper_128.onnx"
unset PYTHONPATH
uv sync
. .venv/bin/activate
'';
};
packages.${system}.default = protestswap;
};
}
# flake-utils.lib.eachDefaultSystem (system: let
# pyproject = builtins.fromTOML (builtins.readFile ./pyproject.toml);
# project = pyproject.project;
#
# package = pkgs.python3Packages.buildPythonPackage {
# pname = project.name;
# inherit (project) version;
# format = "pyproject";
#
# src = ./.;
#
# build-system = with pkgs.python3Packages; [
# uv-build
# ];
#
# # # test dependencies
# nativeCheckInputs = with pkgs; [
# # python3Packages.mypy
# # python3Packages.pytest
# taplo
# ];
#
# # checkPhase = '''';
#
# propagatedBuildInputs = with pkgs; [
# python3Packages.click
# python3Packages.insightface
#
# ] ++ builtins.map (dep: pkgs.python3Packages.${dep}) project.dependencies;
# };
#
# editablePackage = pkgs.python3.pkgs.mkPythonEditablePackage {
# pname = project.name;
# inherit (project) scripts version;
# root = "$PWD";
# };
# in {
# devShells = {
# default = pkgs.mkShell {
# inputsFrom = [
# package
# ];
#
# buildInputs = [
# # our package
# editablePackage
#
# #################
# # VARIOUS TOOLS #
# #################
#
# pkgs.python3Packages.build
# pkgs.python3Packages.ipython
# pkgs.python3Packages.insightface
# inswapperModel
#
# ####################
# # EDITOR/LSP TOOLS #
# ####################
#
# # LSP server:
# pkgs.python3Packages.python-lsp-server
#
# # LSP server plugins of interest:
# pkgs.python3Packages.pylsp-mypy
# pkgs.python3Packages.pylsp-rope
# pkgs.python3Packages.python-lsp-ruff
# ];
# };
# };
#
# packages = {
# "inswapper-model" = inswapperModel;
# "${project.name}" = package;
# default = self.packages.${system}.${project.name};
# };
# });

View file

@ -1,9 +1,22 @@
[project]
name = "hello-python"
version = "0.1.0"
name = "protestswap"
version = "0.0.1"
license-files = ["LICEN[CS]E*"]
description = "A minimal pyproject.toml"
authors = [ ]
requires-python = ">=3.13"
dependencies = [ "insightface", "opencv-python", "matplotlib" ]
dependencies = [
"insightface",
"onnxruntime",
"opencv-python", "matplotlib"
]
[project.scripts]
protestswap-cli = "protestswap.cli:main"
[build-system]
requires = ["uv_build >= 0.8.17, <0.9.0"]
build-backend = "uv_build"
[tool.setuptools.packages]
find = {namespaces = false} # Disable implicit namespaces

View file

29
src/protestswap/cli.py Normal file
View file

@ -0,0 +1,29 @@
import os
import logging
from protestswap.protestswap import ProtestFaceSwapper
logger = logging.getLogger("protestswap")
DEFAULT_INSIGHTFACE_DIR = "/var/lib/insightface"
INSIGHTFACE_VAR = "INSIGHTFACE_ROOT_DIR"
def main():
insightface_dir = None
if os.path.exists(DEFAULT_INSIGHTFACE_DIR):
insightface_dir = DEFAULT_INSIGHTFACE_DIR
elif os.environ.get(INSIGHTFACE_VAR):
insightface_dir = os.environ.get(INSIGHTFACE_VAR)
else:
logger.warning(
f"No directory at '{DEFAULT_INSIGHTFACE_DIR}' and '{INSIGHTFACE_VAR}' not set yet."
)
insightface_dir = f"{os.environ.get('HOME')}/.cache/insightface"
# swapper = ProtestFaceSwapper(insightface_dir)
# swapper.prepare_model()
if __name__ == "__main__":
main()

View file

@ -1,5 +1,8 @@
#!/usr/bin/env python3
import logging
import os
import cv2
import random # TODO: seed!
@ -9,11 +12,14 @@ from insightface.app import FaceAnalysis
from insightface.model_zoo.inswapper import INSwapper
from insightface.app.common import Face
logger = logging.getLogger("protestswap")
SWAPPING_MODEL = 'inswapper_128.onnx'
class Faceswapper:
def __init__(self):
self._app : FaceAnalysis = FaceAnalysis(name='buffalo_l')
class ProtestFaceSwapper:
def __init__(self, root_dir):
self._app : FaceAnalysis = FaceAnalysis(name='buffalo_l', root=insightface_dir)
self._model : INSwapper
self._source : cv2.typing.MatLike|None = None
self._source_faces : list[Face] = []
@ -49,9 +55,9 @@ class Faceswapper:
def main():
swapper = Faceswapper()
swapper.prepare_model()
swapper = ProtestFaceSwapper(insightface_dir)
swapper.prepare_model()
if __name__ == '__main__':