text:
new gridjs.Grid({
    sort: true,
    resizable: true,
    search: true,
    pagination: true,
    pagination: {
      limit: 7,
      summary: true
    },
    fixedHeader: true,
    height: '780px',
    columns: [{
        id: 'creator_username',
        name: 'username',
     }, {
        id: 'model_name',
        name: 'model',
     }, {
        id: 'model_version',
        name: 'version',
     }, {
        id: 'links',
        name: 'links',
        formatter: (cells) => gridjs.html(`<a href='${cells[0]}'>${cells[0].split('/').pop().split('.').pop()}</a>`),
     }, {
        id: 'tokens',
        name: 'tokens',
        width : '300px',
        formatter: (cells) => gridjs.html(`<small>${cells}</small>`),
     }, {
        id: 'vae',
        name: 'vae',
        formatter: (cells) => cells[0] ? gridjs.html(`<a href='${cells[0]}'>vae</a>`) : '',
     }, {
        id: 'online',
        name: 'online',
        formatter: (cells) => gridjs.html(`<a href='${cells[0]}'>colab</a>`),
     }, {
        id: 'images',
        name: 'images',
        width : '350px',
        formatter: (cells) => gridjs.html(`<img src='https://via.placeholder.com/64'> <img src='https://via.placeholder.com/64'> <img src='https://via.placeholder.com/64'> <img src='https://via.placeholder.com/64'>`),
     }, {
        id: 'info',
        name: 'info',
        formatter: (cell) => gridjs.html(`<a href='${cell}'>info</a>`),
     }, {
        id: 'type',
        name: 'type',
     }],
     server: {
        url: 'https://aica.pages.dev/all.json',
        then: data => data.map(creator =>
            [creator.creator_username, creator.model_name, creator.model_version,creator.links,creator.tokens,creator.vae,creator.online,creator.images,creator.info,creator.type]
        )
    },
    style: {
      header  : {
       },
      container : {
       },
      table: {
         color: '#c9d1d9',
         border: '0px',
      },
      th: {
         'background-color': '#161B22',
         color: '#8B949E',
         border: '0px',
      },
      td: {
         'background-color': 'transparent !important',
         border: '0px solid rgb(40 44 50)',
      },
      footer  : {
         'background-color': '#161B22',
         border: '0px',
      }
   },
  }).render(document.getElementById("wrapper"));

var div = document.getElementsByClassName('gridjs-head')[0];
const divInside = document.createElement('div');
divInside.style.textAlign = "right";
divInside.style.color = "#c9d1d9";
divInside.style.paddingTop = "6px";

const json = document.createElement('a');
const jsonSpan = document.createElement('span');
jsonSpan.textContent = ' ' + String.fromCodePoint(128223) + ' ';
json.href = "https://aica.pages.dev/all.json";
json.textContent = 'json';
divInside.appendChild(jsonSpan);
divInside.appendChild(json);

const repo = document.createElement('a');
const repoSpan = document.createElement('span');
repoSpan.textContent = ' ' + String.fromCodePoint(128451) + ' ';
repo.href = "https://github.com/camenduru/ai-creator-archive";
repo.textContent = 'github';
divInside.appendChild(repoSpan);
divInside.appendChild(repo);

const colab = document.createElement('a');
const colabSpan = document.createElement('span');
colabSpan.textContent = ' ' + String.fromCodePoint(129426) + ' ';
colab.href = "https://github.com/camenduru/stable-diffusion-webui-colab";
colab.textContent = 'colab';
divInside.appendChild(colabSpan);
divInside.appendChild(colab);

const cTwitter = document.createElement('a');
const cTwitterSpan = document.createElement('span');
cTwitterSpan.textContent = ' ' + String.fromCodePoint(128035) + ' ';
cTwitter.href = "https://twitter.com/camenduru";
cTwitter.textContent = '@camenduru';
divInside.appendChild(cTwitterSpan);
divInside.appendChild(cTwitter);

div.appendChild(divInside);


text:
```
.
└───creators
    ├───22h
    │   └───vintedois_diffusion
    │       └───010
    ├───852wa
    │   └───8528_diffusion
    │       └───100
    ├───aipicasso
    │   └───cool_japan_diffusion
    │       └───210
    ├───alexds9
    │   └───babes
    │       └───100
    ├───amethyst_vera
    │   └───simp_maker_3k1
    │       └───100
    ├───andite
    │   ├───anything
    │   │   └───400
    │   └───yohan_diffusion
    │       └───100
    ├───astralite_heart
    │   └───pony_diffusion
    │       └───200
    ├───aybeeceedee
    │   └───knollingcase
    │       └───100
    ├───basunat
    │   └───cinematic_diffusion
    │       └───100
    ├───best_jammer
    │   └───hasdx
    │       └───400
    ├───cafeai
    │   └───cafe_instagram_sd_1_5
    │       └───600
    ├───chilon249
    │   └───yiffy_mix
    │       └───100
    ├───claudfuen
    │   └───photorealistic_fuen
    │       └───100
    ├───comp_vis
    │   └───stable_diffusion_original
    │       └───140
    ├───conflictx
    │   └───complex_lineart
    │       └───100
    ├───coreco
    │   └───seek_art_mega
    │       └───100
    ├───dallinmackay
    │   └───van_gogh_diffusion
    │       └───200
    ├───dg_spitzer
    │   └───cyberpunk_anime_diffusion
    │       └───100
    ├───doubleyobro
    │   └───yiffy_e18
    │       └───100
    ├───dreamlike_art
    │   ├───dreamlike_diffusion
    │   │   └───100
    │   └───dreamlike_photoreal
    │       └───200
    ├───duc_haiten
    │   └───duc_haiten_aIart
    │       └───011
    ├───eimiss
    │   └───eimis_anime_diffusion
    │       └───100
    ├───envvi
    │   └───inkpunk_diffusion
    │       └───100
    ├───fiacr
    │   └───comics_blend
    │       └───100
    ├───fictiverse
    │   └───stable_diffusion_paper_cut_model
    │       └───100
    ├───gsdf
    │   └───counterfeit
    │       └───200
    ├───hakurei
    │   └───waifu_diffusion
    │       ├───130
    │       └───140
    ├───hassanblend
    │   └───hassanblend
    │       └───140
    ├───hesw23168
    │   └───sd_elysium_model
    │       └───100
    ├───inzamam567
    │   └───any_gape
    │       └───100
    ├───its_jay_qz
    │   └───synthwave_punk
    │       └───200
    ├───josephus_cheung
    │   ├───a_certainty
    │   │   └───100
    │   ├───a_certain_model
    │   │   └───100
    │   └───a_certain_thing
    │       └───100
    ├───mattgroy
    │   └───dream_like_sam_kuvshinov
    │       └───200
    ├───mehjourney_closed_ai
    │   └───open_anime_journey
    │       └───100
    ├───n75242
    │   └───monstermash_anyv3
    │       └───100
    ├───nitrosocke
    │   ├───arcane_diffusion
    │   │   └───300
    │   └───mo_di_diffusion
    │       └───100
    ├───ogkalu
    │   ├───comic_diffusion
    │   │   └───200
    │   └───illustration_diffusion
    │       └───100
    ├───plasmo
    │   ├───food_crit
    │   │   └───100
    │   └───woolitize
    │       └───100
    ├───prompthero
    │   ├───midjourney_diffusion
    │   │   └───400
    │   └───openjourney
    │       └───200
    ├───public_prompts
    │   └───all_in_one_pixel_model
    │       └───100
    ├───ray_hell
    │   └───popup_book_diffusion
    │       └───100
    ├───riffusion
    │   └───riffusion_model
    │       └───100
    ├───runwayml
    │   ├───stable_diffusion
    │   │   └───150
    │   └───stable_diffusion_inpainting
    │       └───100
    ├───sandro_halpo
    │   └───sam_does_art
    │       └───300
    ├───sentet1c
    │   └───rando_mix3
    │       └───100
    ├───stabilityai
    │   ├───stable_diffusion
    │   │   ├───200
    │   │   └───210
    │   ├───stable_diffusion_base
    │   │   ├───200
    │   │   └───210
    │   ├───stable_diffusion_depth
    │   │   └───200
    │   └───stable_diffusion_inpainting
    │       └───200
    ├───thecollector
    │   └───sam_does_sexy_blend
    │       └───100
    ├───unknown
    │   ├───anything
    │   │   └───300
    │   ├───elldreths_lucid_mix
    │   │   └───100
    │   ├───f222
    │   │   └───100
    │   ├───grapefruit
    │   │   └───100
    │   ├───iz
    │   │   └───100
    │   ├───protogen
    │   │   └───220
    │   ├───rbm
    │   │   └───100
    │   └───urp
    │       └───100
    ├───warrior_mama777
    │   └───orange_mixs
    │       └───100
    └───wavymulder
        └───analog_diffusion
            └───100

repo_name: camenduru/ai-creator-archive

repo_language: Jupyter Notebook

mime_type: text/plain


text:
526_mix_webui_colab
7th_layer_webui_colab
8528_diffusion_webui_colab
a_certain_model_webui_colab
a_certain_thing_webui_colab
a_certainty_webui_colab
abyss_orange_mix_2_webui_colab
abyss_orange_mix_3_webui_colab
alfamix_webui_colab
all_in_one_pixel_model_webui_colab
analog_diffusion_webui_colab
anylora_webui_colab
anything_3_webui_colab
anything_4_webui_colab
anything_gape_webui_colab
arcane_diffusion_3_webui_colab
babes_blend_webui_colab
berry_mix_1_5_webui_colab
cafe_instagram_v6_webui_colab
cetus_mix_v3_1_webui_colab
cheese_daddys_landscapes_mix_webui_colab
chillout_mix_webui_colab
cinematic_diffusion_webui_colab
color_bomb_mix_webui_colab
comic_diffusion_v2_webui_colab
comics_blend_webui_colab
complex_lineart_webui_colab
cool_japan_diffusion_2_1_webui_colab
counterfeit_v2_0_webui_colab
cyberpunk_anime_diffusion_webui_colab
dark_sushi_mix_mix_webui_colab
defmix_v2_webui_colab
deliberate_webui_colab
dosmix_webui_colab
dpepmkmp_webui_colab
dream_like_sam_kuvshino_webui_colab
dreamlike_diffusion_1_webui_colab
dreamlike_photoreal_2_webui_colab
dreamshaper_3_32_webui_colab
duchaitenaiart_v1_1_webui_colab
eimis_anime_diffusion_1_webui_colab
elldreths_lucid_mix_v10_webui_colab
elysium_anime_2_webui_colab
experience_webui_colab
f222_webui_colab
faetastic_v1_webui_colab
fantasy_world_v1_webui_colab
food_crit_webui_colab
grapefruit_webui_colab
graphic_art_webui_colab
hasdx_webui_colab
hassan_blend_1_4_webui_colab
illustration_diffusion_webui_colab
inkpunk_webui_colab
izumi_v1_webui_colab
knollingcase_webui_colab
liberty_webui_colab
lucky_strike_mix_webui_colab
magical_mix_v1_webui_colab
magical_mix_v2_webui_colab
mare_coloris_webui_colab
meina_mix_v8_webui_colab
midjourney_v4_diffusion_webui_colab
mo_di_diffusion_webui_colab
monstermash_any_3_webui_colab
mousey_mix_webui_colab
neverending_dream_webui_colab
nostalgia_clear_webui_colab
open_anime_journey_webui_colab
openjourney_v2_diffusion_webui_colab
openjourney_v4_webui_colab
padoru_v1_webui_colab
papercut_diffusion_webui_colab
pastel_boys_2d_webui_colab
pastel_mix_stylized_anime_webui_colab
pegasus_9_mix_webui_colab
perfect_world_v2_webui_colab
photorealistic_fuen_v1_webui_colab
pony_diffusion_2_webui_colab
pony_diffusion_v3_webui_colab
pony_v4_webui_colab
popup_book_diffusion_webui_colab
protogen_nova_webui_colab
protogen_v2_2_webui_colab
protogen_x3_4_webui_colab
pvc_v3_webui_colab
rando_mix_3_webui_colab
realbiter_v1_0_webui_colab
realistic_vision_v13_webui_colab
realistic_vision_v20_webui_colab
refslave_v2_webui_colab
rev_animated_v1_1_webui_colab
rmada_merge_v5_webui_colab
rmadart_v5_webui_colab
robo_diffusion_webui_colab
rpg_v4_webui_colab
samdoesart_diffusion_webui_colab
samdoessexy_blend_webui_colab
seek_art_mega_v1_webui_colab
seekart_mega_webui_colab
simpmaker_3k_webui_colab
stable_diffusion_1_5_webui_colab
stable_diffusion_inpainting_webui_colab
stable_diffusion_v2_1_base_webui_colab
stable_diffusion_v2_1_webui_colab
stable_diffusion_v2_base_webui_colab
stable_diffusion_v2_depth_webui_colab
stable_diffusion_v2_inpainting_webui_colab
stable_diffusion_v2_webui_colab
stable_diffusion_webui_colab
stablydiffuseds_aesthetic_mix_webui_colab
sukiyaki_mix_v1_webui_colab
synthwave_punk_v2_webui_colab
uber_realistic_merge_webui_colab
uber_realistic_v1_webui_colab
van_gogh_diffusion_webui_colab
vinte_protogen_mix_v_1_0_webui_colab
vintedois_diffusion_0_1_webui_colab
voxo_webui_colab
waifu_diffusion_v1_4_webui_colab
waifu_diffusion_v1_5_b2_webui_colab
waifu_diffusion_v1_5_webui_colab
waifu_diffusion_webui_colab
woolitize_webui_colab
yiffy_e18_webui_colab
yiffy_mix_webui_colab
yohan_diffusion_webui_colab


text:
mo_di_diffusion_webui_colab 1080129500274245744
vinte_protogen_mix_v_1_0_webui_colab 1080132398781575249
waifu_diffusion_v1_5_b2_webui_colab 1084979718358581310
stablydiffuseds_aesthetic_mix_webui_colab 1084979612800532561
graphic_art_webui_colab 1084979552809390202
pvc_v3_webui_colab 1084979506370068511
magical_mix_v1_webui_colab 1084979421561225216
voxo_webui_colab 1084979382910722198
padoru_v1_webui_colab 1084979343165497455
realistic_vision_v13_webui_colab 1084979258084036658
liberty_webui_colab 1084978412449435719
sukiyaki_mix_v1_webui_colab 1084978296300785846
alfamix_webui_colab 1084978268471570572
mare_coloris_webui_colab 1084978193582268449
defmix_v2_webui_colab 1084978124464337037
perfect_world_v2_webui_colab 1084978094504415374
refslave_v2_webui_colab 1084977996877799445
uber_realistic_v1_webui_colab 1080131357151342693
stable_diffusion_inpainting_webui_colab 1080128693445333003
stable_diffusion_1_5_webui_colab 1080129446108999700
riffusion_v1_webui_colab 1080131014803849316
waifu_diffusion_webui_colab 1080128404529094779
stable_diffusion_webui_colab 1080128346282807396
cafe_instagram_v6_webui_colab 1080131169376542850
vintedois_diffusion_0_1_webui_colab 1080130677518893068
cinematic_diffusion_webui_colab 1080131208354209902
all_in_one_pixel_model_webui_colab 1080131135079718942
illustration_diffusion_webui_colab 1080130898294476810
synthwave_punk_v2_webui_colab 1080130861443334234
8528_diffusion_webui_colab 1080131632238973010
popup_book_diffusion_webui_colab 1080157291489284146
chillout_mix_webui_colab 1080132425121792000
food_crit_webui_colab 1080131252029501440
openjourney_v2_diffusion_webui_colab 1080130644094496768
waifu_diffusion_v1_4_webui_colab 1080131045032218624
dream_like_sam_kuvshino_webui_colab 1080131599846350969
abyss_orange_mix_2_webui_colab 1080131688723660880
dreamlike_photoreal_2_webui_colab 1080131718624854058
cool_japan_diffusion_2_1_webui_colab 1080131786685816933
a_certain_model_webui_colab 1080131985701347338
a_certain_thing_webui_colab 1080132011580194896
pix2pix_webui_colab 1080132066676592682
protogen_nova_webui_colab 1080132153448337468
protogen_x3_4_webui_colab 1080132256229761025
neverending_dream_webui_colab 1080132340967276666
deliberate_webui_colab 1080132367886323832
pastel_mix_stylized_anime_webui_colab 1080132454318362654
comics_blend_webui_colab 1080131565423693844
woolitize_webui_colab 1080129883839139910
mousey_mix_webui_colab 1080132554667077683
illuminati_v1_0_webui_colab 1080132498975105137
seek_art_mega_v1_webui_colab 1080130939881013298
yohan_diffusion_webui_colab 1080130612255527044
eimis_anime_diffusion_1_webui_colab 1080130422073204757
comic_diffusion_v2_webui_colab 1080130785421574144
pony_diffusion_2_webui_colab 1080130350036045884
hassan_blend_1_4_webui_colab 1080130284932051034
complex_lineart_webui_colab 1080130827058434119
analog_diffusion_webui_colab 1080130538855223376
van_gogh_diffusion_webui_colab 1080130502817763408
dreamlike_diffusion_1_webui_colab 1080130468923572424
knollingcase_webui_colab 1080130718602104862
inkpunk_webui_colab 1080129920904204288
samdoesart_diffusion_webui_colab 1080129807389577266
arcane_diffusion_3_webui_colab 1080129552090660905
cyberpunk_anime_diffusion_webui_colab 1080129636559753336
midjourney_v4_diffusion_webui_colab 1080129702393565345
papercut_diffusion_webui_colab 1080129755841560596
illuminati_v1_1_webui_colab 1080132633478041760
dpepmkmp_webui_colab 1080132588498337923
color_bomb_mix_webui_colab 1080132529090220083
abyss_orange_mix_3_webui_colab 1080132313511370914
dreamshaper_3_32_webui_colab 1080132287972245625
control_net_webui_colab 1080132217918984202
waifu_diffusion_v1_5_webui_colab 1080132126013411328
rpg_v4_webui_colab 1080132097626362006
7th_layer_webui_colab 1080132038008524850
a_certainty_webui_colab 1080131961835753524
open_anime_journey_webui_colab 1080131929740939355
grapefruit_webui_colab 1080131900976398386
counterfeit_v2_0_webui_colab 1080131874346762360
anything_4_webui_colab 1080131842046447626
anything_gape_webui_colab 1080131813881683978
photorealistic_fuen_v1_webui_colab 1080131747724922932
hasdx_webui_colab 1080131659652935701
samdoessexy_blend_webui_colab 1080131516165791754
babes_blend_webui_colab 1080131446729093120
yiffy_mix_webui_colab 1080131418543357963
izumi_v1_webui_colab 1080131390261178378
duchaitenaiart_v1_1_webui_colab 1080131316927955037
simpmaker_3k_webui_colab 1080131284594077726
elldreths_lucid_mix_v10_webui_colab 1080131098618646548
protogen_v2_2_webui_colab 1080131071355662397
monstermash_any_3_webui_colab 1080130573621800992
elysium_anime_2_webui_colab 1080130383510777896
yiffy_e18_webui_colab 1080130319220486166
stable_diffusion_v2_inpainting_webui_colab 1080130243379089479
stable_diffusion_v2_depth_webui_colab 1080130213188468738
stable_diffusion_v2_base_webui_colab 1080130182184194078
stable_diffusion_v2_webui_colab 1080130150672384102
stable_diffusion_v2_1_base_webui_colab 1080130120758595744
stable_diffusion_v2_1_webui_colab 1080130090173734922
berry_mix_1_5_webui_colab 1080130044237713408
f222_webui_colab 1080130010117058600
rando_mix_3_webui_colab 1080129971240050718
anything_3_webui_colab 1080129845834567730


text:
🐣 Please follow me for new updates https://twitter.com/camenduru

🔥 Please join our discord server https://discord.gg/k5BwmmvJJU

🥳 Please join my patreon community https://patreon.com/camenduru

## 🚦WIP🚦

## JSON & Preview

JSON: https://aica.pages.dev/all.json

Preview Grid: https://aica.vercel.app

Preview Table: https://aica.pages.dev

## Motivation and Action

Maybe someday, your favorite AI company will force you to make your stable diffusion models private. It's time to copy and paste them to other cloud providers to ensure they can't be taken down. This repo will begin with 105 models from the [stable-diffusion-webui-colab](https://github.com/camenduru/stable-diffusion-webui-colab) project and will provide a simple JSON file for the data inside. It will continue to grow.

## What is the AI Creator Archive

An AI Creator Archive is a repository of information about the individuals and teams who create and develop artificial intelligence models.
The archive can include information such as the creators' notable contributions to the field of AI.
It also include information about the AI models they have developed.
The purpose of an AI Creator Archive is to provide transparency and recognition for the creators of AI models.
It is also useful for people who are interested in learning about the history and development of AI and the people behind it.

## Contributing to the AI Creator Archive
Just open an issue with your `username`, `model name`, `model version`, `model token(s)`, `model direct link` or `Google Drive link`, `4 images with PNG info`, and if you want, an `info.txt`

## Image Formats
Images should not contain any nudity. Remember how GitHub deleted the web UI without warning.

## Automation Design

All files and the Colab notebook will be created with the server, the Colab will be published on this link: https://github.com/camenduru/stable-diffusion-webui-colab

### Folder Structure

```
.
├── ...
├── creator_username          # username format if UseR_Nam3 should be user_nam3
│   └── model_name            # model name format if OrangeCocoaMix should be orange_cocoa_mix
│       └── model_version     # model version format if v0.1.0 should be 0_1_0
│           ├── 1.png         # 4 images should be generated for each version
│           ├── 2.png         # using the corresponding model version
│           ├── 3.png         # the PNG info should be included within the images
│           ├── 4.png         # all images will auto regenerated with the PNG info and overwrite these four images
│           ├── links.txt     # check links.txt format
│           ├── tokens.txt    # check tokens.txt format
│           ├── online.txt    # check online.txt format
│           ├── images.txt    # check images.txt format
│           ├── type.txt      # check type.txt format
│           ├── vae.txt       # check vae.txt format
│           └── info.txt      # check info.txt format
├── all.json
└── ...
```

#### links.txt format

```
Models should be PyTorch safetensors format if not please convert with this https://github.com/camenduru/converter-colab
Each line must contain one direct link to the model, not the model page. The magnet should contain only the model.

├── https://huggingface.co/ckpt/stable-diffusion-2/resolve/main/768-v-ema.ckpt
├── https://civitai.com/api/download/models/0000?type=Pruned%20Model&format=SafeTensor
└── magnet:?xt=urn:btih:000000&dn=model&tr=udp://tracker.com&tr=udp://tracker.org/announce
```

#### tokens.txt format

```
Each line must contain one token.

├── analog style
└── dreamlikeart style
```

#### online.txt format

```
Online service links, such as Google Colab
Each line must contain one link.

├── https://colab.research.google.com/github/camenduru/stable-diffusion-webui-colab/blob/main/stable/stable_diffusion_webui_colab.ipynb
```

#### images.txt format

```
4 images should be generated for each version using the corresponding model version
The PNG info should be included within the images
All images will auto regenerated with the PNG info and overwrite these four images
Each line must contain one image url.

├── https://aica.pages.dev/creators/basunat/cinematic_diffusion/1_0_0/1.png
├── https://aica.pages.dev/creators/basunat/cinematic_diffusion/1_0_0/2.png
├── https://aica.pages.dev/creators/basunat/cinematic_diffusion/1_0_0/3.png
└── https://aica.pages.dev/creators/basunat/cinematic_diffusion/1_0_0/4.png
```

#### type.txt format

```
fine_tune, dreambooth, textual_inversion, hypernetwork, aesthetic_gradient, lora, blend
```

#### vae.txt format

```
VAE link for the model, name should be same_name_with_model.vae.pt
Each line must contain one link.

├── https://huggingface.co/ckpt/sd-vae-ft-mse-original/resolve/main/vae-ft-mse-840000-ema-pruned.ckpt
```

#### info.txt format

```
info.txt file will follow the markdown guide, with a file size of 10KB, do whatever you want. maybe example prompts.
```

#### all.json
```
all.json contains all of the data inside the files links.txt, tokens.txt, online.txt, info.txt, and image links.

[
    {
        "creator_username": "22h",
        "images": [
            "https://aica.pages.dev/creators/22h/vintedois_diffusion/0_1_0/1.png",
            "https://aica.pages.dev/creators/22h/vintedois_diffusion/0_1_0/2.png",
            "https://aica.pages.dev/creators/22h/vintedois_diffusion/0_1_0/3.png",
            "https://aica.pages.dev/creators/22h/vintedois_diffusion/0_1_0/4.png"
        ],
        "info": "https://aica.pages.dev/creators/22h/vintedois_diffusion/0_1_0/info.txt",
        "links": [
            "https://huggingface.co/ckpt/vintedois-diffusion-v0-1/resolve/main/vintedois_0_1.ckpt"
        ],
        "model_name": "vintedois_diffusion",
        "model_version": "0_1_0",
        "online": [
            "https://colab.research.google.com/github/camenduru/stable-diffusion-webui-colab/blob/main/stable/vintedois_diffusion_0_1_webui_colab.ipynb"
        ],
        "tokens": [
            "estilovintedois"
        ],
        "type": [
            "dreambooth"
        ],
        "vae": []
    },
    {
        "creator_username": "852wa",
        "images": [
            "https://aica.pages.dev/creators/852wa/8528_diffusion/1_0_0/1.png",
            "https://aica.pages.dev/creators/852wa/8528_diffusion/1_0_0/2.png",
            "https://aica.pages.dev/creators/852wa/8528_diffusion/1_0_0/3.png",
            "https://aica.pages.dev/creators/852wa/8528_diffusion/1_0_0/4.png"
        ],
        "info": "https://aica.pages.dev/creators/852wa/8528_diffusion/1_0_0/info.txt",
        "links": [
            "https://huggingface.co/ckpt/8528-diffusion/resolve/main/8528d-final.ckpt"
        ],
        "model_name": "8528_diffusion",
        "model_version": "1_0_0",
        "online": [
            "https://colab.research.google.com/github/camenduru/stable-diffusion-webui-colab/blob/main/stable/8528_diffusion_webui_colab.ipynb"
        ],
        "tokens": [],
        "type": [
            "fine_tune"
        ],
        "vae": []
    }
]
```

## Archive PyTorch Backup

All PyTorch safetensors and ckpt models in this archive will be stored at this link: https://huggingface.co/ckpt and the link will be written in the 'models links.txt' file.
If we can find more cloud storage sponsors, we will create multiple backups, including backups of backups and backups of backups of backups of backups of ...

We will also publish reports on the relationships between each model and its parent models, as well as the mixture percentages.

## Archive Flax Diffusers Lib Backup
All Flax Diffusers Lib safetensors and msgpack weights in this archive will be stored at this link: https://huggingface.co/flax and the link will be written in the 'models flax-links.txt' file.

## Archive PyTorch Diffusers Lib Backup
All PyTorch Diffusers Lib safetensors and bin weights in this archive will be stored at this link: https://huggingface.co/flax `pytorch` branch and the link will be written in the 'models pt-links.txt' file.

## Archive Core ML Backup
All Core ML Models in this archive will be stored at this link: https://huggingface.co/core-ml and the link will be written in the 'models coreml-links.txt' file.

## Archive Embed Backup
Textual Inversion, LoRA models will be stored at this link: https://huggingface.co/embed (Another archival project will be announced soon)

## Archive TensorRT Backup
TensorRT models will be stored at this link: https://huggingface.co/trrt (Another archival project will be announced soon)


text:
# These are supported funding model platforms

github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: camenduru
open_collective: # Replace with a single Open Collective username
ko_fi: camenduru
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']


text:
https://aica.pages.dev/creators/vsukiyaki/sukiyaki_mix/1_0_0/1.png
https://aica.pages.dev/creators/vsukiyaki/sukiyaki_mix/1_0_0/2.png
https://aica.pages.dev/creators/vsukiyaki/sukiyaki_mix/1_0_0/3.png
https://aica.pages.dev/creators/vsukiyaki/sukiyaki_mix/1_0_0/4.png


text:
https://aica.pages.dev/creators/inzamam567/any_gape/1_0_0/1.png
https://aica.pages.dev/creators/inzamam567/any_gape/1_0_0/2.png
https://aica.pages.dev/creators/inzamam567/any_gape/1_0_0/3.png
https://aica.pages.dev/creators/inzamam567/any_gape/1_0_0/4.png


text:
https://aica.pages.dev/creators/jawgboi/padoru/1_0_0/1.png
https://aica.pages.dev/creators/jawgboi/padoru/1_0_0/2.png
https://aica.pages.dev/creators/jawgboi/padoru/1_0_0/3.png
https://aica.pages.dev/creators/jawgboi/padoru/1_0_0/4.png


text:
https://aica.pages.dev/creators/claudfuen/photorealistic_fuen/1_0_0/1.png
https://aica.pages.dev/creators/claudfuen/photorealistic_fuen/1_0_0/2.png
https://aica.pages.dev/creators/claudfuen/photorealistic_fuen/1_0_0/3.png
https://aica.pages.dev/creators/claudfuen/photorealistic_fuen/1_0_0/4.png


text:
https://aica.pages.dev/creators/civitai/chilloutmix/1_0_0/1.png
https://aica.pages.dev/creators/civitai/chilloutmix/1_0_0/2.png
https://aica.pages.dev/creators/civitai/chilloutmix/1_0_0/3.png
https://aica.pages.dev/creators/civitai/chilloutmix/1_0_0/4.png


text:
https://aica.pages.dev/creators/fiacr/comics_blend/1_0_0/1.png
https://aica.pages.dev/creators/fiacr/comics_blend/1_0_0/2.png
https://aica.pages.dev/creators/fiacr/comics_blend/1_0_0/3.png
https://aica.pages.dev/creators/fiacr/comics_blend/1_0_0/4.png


text:
ComplexLA style
nvinkpunk
marioalberti artstyle
ghibli style


text:
https://aica.pages.dev/creators/illuminati_ai/illuminati/1_1_0/1.png
https://aica.pages.dev/creators/illuminati_ai/illuminati/1_1_0/2.png
https://aica.pages.dev/creators/illuminati_ai/illuminati/1_1_0/3.png
https://aica.pages.dev/creators/illuminati_ai/illuminati/1_1_0/4.png


text:
https://aica.pages.dev/creators/fictiverse/stable_diffusion_paper_cut_model/1_0_0/1.png
https://aica.pages.dev/creators/fictiverse/stable_diffusion_paper_cut_model/1_0_0/2.png
https://aica.pages.dev/creators/fictiverse/stable_diffusion_paper_cut_model/1_0_0/3.png
https://aica.pages.dev/creators/fictiverse/stable_diffusion_paper_cut_model/1_0_0/4.png


text:
https://aica.pages.dev/creators/22h/vintedois_diffusion/0_1_0/1.png
https://aica.pages.dev/creators/22h/vintedois_diffusion/0_1_0/2.png
https://aica.pages.dev/creators/22h/vintedois_diffusion/0_1_0/3.png
https://aica.pages.dev/creators/22h/vintedois_diffusion/0_1_0/4.png


text:
https://aica.pages.dev/creators/shatalin_art/alfamix/1_0_0/1.png
https://aica.pages.dev/creators/shatalin_art/alfamix/1_0_0/2.png
https://aica.pages.dev/creators/shatalin_art/alfamix/1_0_0/3.png
https://aica.pages.dev/creators/shatalin_art/alfamix/1_0_0/4.png


text:
https://aica.pages.dev/creators/mekabu/magical_mix/1_0_0/1.png
https://aica.pages.dev/creators/mekabu/magical_mix/1_0_0/2.png
https://aica.pages.dev/creators/mekabu/magical_mix/1_0_0/3.png
https://aica.pages.dev/creators/mekabu/magical_mix/1_0_0/4.png


text:
https://aica.pages.dev/creators/public_prompts/all_in_one_pixel_model/1_0_0/1.png
https://aica.pages.dev/creators/public_prompts/all_in_one_pixel_model/1_0_0/2.png
https://aica.pages.dev/creators/public_prompts/all_in_one_pixel_model/1_0_0/3.png
https://aica.pages.dev/creators/public_prompts/all_in_one_pixel_model/1_0_0/4.png


text:
pixelsprite
16bitscene


text:
https://aica.pages.dev/creators/defpoint/defmix/2_0_0/1.png
https://aica.pages.dev/creators/defpoint/defmix/2_0_0/2.png
https://aica.pages.dev/creators/defpoint/defmix/2_0_0/3.png
https://aica.pages.dev/creators/defpoint/defmix/2_0_0/4.png


text:
https://aica.pages.dev/creators/stablydiffused/stablydiffuseds_aesthetic_mix/1_0_0/1.png
https://aica.pages.dev/creators/stablydiffused/stablydiffuseds_aesthetic_mix/1_0_0/2.png
https://aica.pages.dev/creators/stablydiffused/stablydiffuseds_aesthetic_mix/1_0_0/3.png
https://aica.pages.dev/creators/stablydiffused/stablydiffuseds_aesthetic_mix/1_0_0/4.png


text:
https://aica.pages.dev/creators/mattgroy/dream_like_sam_kuvshinov/2_0_0/1.png
https://aica.pages.dev/creators/mattgroy/dream_like_sam_kuvshinov/2_0_0/2.png
https://aica.pages.dev/creators/mattgroy/dream_like_sam_kuvshinov/2_0_0/3.png
https://aica.pages.dev/creators/mattgroy/dream_like_sam_kuvshinov/2_0_0/4.png


text:
https://aica.pages.dev/creators/darkstorm2150/protogen_nova/1_0_0/1.png
https://aica.pages.dev/creators/darkstorm2150/protogen_nova/1_0_0/2.png
https://aica.pages.dev/creators/darkstorm2150/protogen_nova/1_0_0/3.png
https://aica.pages.dev/creators/darkstorm2150/protogen_nova/1_0_0/4.png


text:
https://aica.pages.dev/creators/darkstorm2150/protogen_x/3_4_0/1.png
https://aica.pages.dev/creators/darkstorm2150/protogen_x/3_4_0/2.png
https://aica.pages.dev/creators/darkstorm2150/protogen_x/3_4_0/3.png
https://aica.pages.dev/creators/darkstorm2150/protogen_x/3_4_0/4.png


text:
https://huggingface.co/ckpt/SD-Elysium-Model/resolve/main/Elysium_Anime_V2.ckpt
https://huggingface.co/ckpt/SD-Elysium-Model/resolve/main/Elysium_Anime_V3.safetensors


text:
https://aica.pages.dev/creators/hesw23168/sd_elysium_model/1_0_0/1.png
https://aica.pages.dev/creators/hesw23168/sd_elysium_model/1_0_0/2.png
https://aica.pages.dev/creators/hesw23168/sd_elysium_model/1_0_0/3.png
https://aica.pages.dev/creators/hesw23168/sd_elysium_model/1_0_0/4.png


text:
https://aica.pages.dev/creators/852wa/8528_diffusion/1_0_0/1.png
https://aica.pages.dev/creators/852wa/8528_diffusion/1_0_0/2.png
https://aica.pages.dev/creators/852wa/8528_diffusion/1_0_0/3.png
https://aica.pages.dev/creators/852wa/8528_diffusion/1_0_0/4.png


text:
https://aica.pages.dev/creators/coreco/seek_art_mega/1_0_0/1.png
https://aica.pages.dev/creators/coreco/seek_art_mega/1_0_0/2.png
https://aica.pages.dev/creators/coreco/seek_art_mega/1_0_0/3.png
https://aica.pages.dev/creators/coreco/seek_art_mega/1_0_0/4.png


text:
https://aica.pages.dev/creators/dallinmackay/van_gogh_diffusion/2_0_0/1.png
https://aica.pages.dev/creators/dallinmackay/van_gogh_diffusion/2_0_0/2.png
https://aica.pages.dev/creators/dallinmackay/van_gogh_diffusion/2_0_0/3.png
https://aica.pages.dev/creators/dallinmackay/van_gogh_diffusion/2_0_0/4.png


text:
https://aica.pages.dev/creators/bloodsuga/perfect_world/2_0_0/1.png
https://aica.pages.dev/creators/bloodsuga/perfect_world/2_0_0/2.png
https://aica.pages.dev/creators/bloodsuga/perfect_world/2_0_0/3.png
https://aica.pages.dev/creators/bloodsuga/perfect_world/2_0_0/4.png


text:
https://aica.pages.dev/creators/thecollector/sam_does_sexy_blend/1_0_0/1.png
https://aica.pages.dev/creators/thecollector/sam_does_sexy_blend/1_0_0/2.png
https://aica.pages.dev/creators/thecollector/sam_does_sexy_blend/1_0_0/3.png
https://aica.pages.dev/creators/thecollector/sam_does_sexy_blend/1_0_0/4.png


text:
https://aica.pages.dev/creators/hakurei/waifu_diffusion/1_4_0/1.png
https://aica.pages.dev/creators/hakurei/waifu_diffusion/1_4_0/2.png
https://aica.pages.dev/creators/hakurei/waifu_diffusion/1_4_0/3.png
https://aica.pages.dev/creators/hakurei/waifu_diffusion/1_4_0/4.png


text:
https://aica.pages.dev/creators/hakurei/waifu_diffusion/1_3_0/1.png
https://aica.pages.dev/creators/hakurei/waifu_diffusion/1_3_0/2.png
https://aica.pages.dev/creators/hakurei/waifu_diffusion/1_3_0/3.png
https://aica.pages.dev/creators/hakurei/waifu_diffusion/1_3_0/4.png


text:
https://aica.pages.dev/creators/dg_spitzer/cyberpunk_anime_diffusion/1_0_0/1.png
https://aica.pages.dev/creators/dg_spitzer/cyberpunk_anime_diffusion/1_0_0/2.png
https://aica.pages.dev/creators/dg_spitzer/cyberpunk_anime_diffusion/1_0_0/3.png
https://aica.pages.dev/creators/dg_spitzer/cyberpunk_anime_diffusion/1_0_0/4.png


text:
https://aica.pages.dev/creators/riffusion/riffusion_model/1_0_0/1.png
https://aica.pages.dev/creators/riffusion/riffusion_model/1_0_0/2.png
https://aica.pages.dev/creators/riffusion/riffusion_model/1_0_0/3.png
https://aica.pages.dev/creators/riffusion/riffusion_model/1_0_0/4.png


text:
https://aica.pages.dev/creators/conflictx/complex_lineart/1_0_0/1.png
https://aica.pages.dev/creators/conflictx/complex_lineart/1_0_0/2.png
https://aica.pages.dev/creators/conflictx/complex_lineart/1_0_0/3.png
https://aica.pages.dev/creators/conflictx/complex_lineart/1_0_0/4.png


text:
https://aica.pages.dev/creators/p1atdev/pvc/3_0_0/1.png
https://aica.pages.dev/creators/p1atdev/pvc/3_0_0/2.png
https://aica.pages.dev/creators/p1atdev/pvc/3_0_0/3.png
https://aica.pages.dev/creators/p1atdev/pvc/3_0_0/4.png


text:
https://huggingface.co/ckpt/DucHaitenAIart_v1.1a/resolve/main/DucHaitenAIart_v1.1a_emaonly.ckpt
https://huggingface.co/ckpt/DucHaitenAIart_v2.0/resolve/main/DucHaitenAIart_v2.0-emaonly.safetensors
https://huggingface.co/DucHaiten/DucHaitenDarkside/resolve/main/DucHaitenDarkside_v1.0.safetensors


text:
https://aica.pages.dev/creators/duc_haiten/duc_haiten_ai_art/0_1_1/1.png
https://aica.pages.dev/creators/duc_haiten/duc_haiten_ai_art/0_1_1/2.png
https://aica.pages.dev/creators/duc_haiten/duc_haiten_ai_art/0_1_1/3.png
https://aica.pages.dev/creators/duc_haiten/duc_haiten_ai_art/0_1_1/4.png


text:
https://aica.pages.dev/creators/aine_captain/liberty/1_0_0/1.png
https://aica.pages.dev/creators/aine_captain/liberty/1_0_0/2.png
https://aica.pages.dev/creators/aine_captain/liberty/1_0_0/3.png
https://aica.pages.dev/creators/aine_captain/liberty/1_0_0/4.png


text:
https://aica.pages.dev/creators/ratkovm8640/dream_like_sam_kuvshino/1_0_0/1.png
https://aica.pages.dev/creators/ratkovm8640/dream_like_sam_kuvshino/1_0_0/2.png
https://aica.pages.dev/creators/ratkovm8640/dream_like_sam_kuvshino/1_0_0/3.png
https://aica.pages.dev/creators/ratkovm8640/dream_like_sam_kuvshino/1_0_0/4.png


text:
https://aica.pages.dev/creators/best_jammer/hasdx/4_0_0/1.png
https://aica.pages.dev/creators/best_jammer/hasdx/4_0_0/2.png
https://aica.pages.dev/creators/best_jammer/hasdx/4_0_0/3.png
https://aica.pages.dev/creators/best_jammer/hasdx/4_0_0/4.png


text:
https://aica.pages.dev/creators/aybeeceedee/knollingcase/1_0_0/1.png
https://aica.pages.dev/creators/aybeeceedee/knollingcase/1_0_0/2.png
https://aica.pages.dev/creators/aybeeceedee/knollingcase/1_0_0/3.png
https://aica.pages.dev/creators/aybeeceedee/knollingcase/1_0_0/4.png


text:
https://aica.pages.dev/creators/waifu_diffusion/waifu_diffusion/1_5_0/1.png
https://aica.pages.dev/creators/waifu_diffusion/waifu_diffusion/1_5_0/2.png
https://aica.pages.dev/creators/waifu_diffusion/waifu_diffusion/1_5_0/3.png
https://aica.pages.dev/creators/waifu_diffusion/waifu_diffusion/1_5_0/4.png


text:
https://aica.pages.dev/creators/waifu_diffusion/waifu_diffusion/1_5_2/1.png
https://aica.pages.dev/creators/waifu_diffusion/waifu_diffusion/1_5_2/2.png
https://aica.pages.dev/creators/waifu_diffusion/waifu_diffusion/1_5_2/3.png
https://aica.pages.dev/creators/waifu_diffusion/waifu_diffusion/1_5_2/4.png


text:
https://aica.pages.dev/creators/eimiss/eimis_anime_diffusion/1_0_0/1.png
https://aica.pages.dev/creators/eimiss/eimis_anime_diffusion/1_0_0/2.png
https://aica.pages.dev/creators/eimiss/eimis_anime_diffusion/1_0_0/3.png
https://aica.pages.dev/creators/eimiss/eimis_anime_diffusion/1_0_0/4.png


text:
https://aica.pages.dev/creators/agra_fl/refslave/2_0_0/1.png
https://aica.pages.dev/creators/agra_fl/refslave/2_0_0/2.png
https://aica.pages.dev/creators/agra_fl/refslave/2_0_0/3.png
https://aica.pages.dev/creators/agra_fl/refslave/2_0_0/4.png


text:
https://aica.pages.dev/creators/nitrosocke/mo_di_diffusion/1_0_0/1.png
https://aica.pages.dev/creators/nitrosocke/mo_di_diffusion/1_0_0/2.png
https://aica.pages.dev/creators/nitrosocke/mo_di_diffusion/1_0_0/3.png
https://aica.pages.dev/creators/nitrosocke/mo_di_diffusion/1_0_0/4.png


text:
https://aica.pages.dev/creators/nitrosocke/arcane_diffusion/3_0_0/1.png
https://aica.pages.dev/creators/nitrosocke/arcane_diffusion/3_0_0/2.png
https://aica.pages.dev/creators/nitrosocke/arcane_diffusion/3_0_0/3.png
https://aica.pages.dev/creators/nitrosocke/arcane_diffusion/3_0_0/4.png


text:
https://aica.pages.dev/creators/lykon/neverending_dream/1_0_0/1.png
https://aica.pages.dev/creators/lykon/neverending_dream/1_0_0/2.png
https://aica.pages.dev/creators/lykon/neverending_dream/1_0_0/3.png
https://aica.pages.dev/creators/lykon/neverending_dream/1_0_0/4.png


text:
https://huggingface.co/ckpt/monstermash_anyv3/resolve/main/monstermash4%2Banyv3.safetensors
https://huggingface.co/ckpt/monstermash_anyv3/resolve/main/monstermash6%2Banyv3.safetensors


text:
https://aica.pages.dev/creators/n75242/monstermash_anyv3/1_0_0/1.png
https://aica.pages.dev/creators/n75242/monstermash_anyv3/1_0_0/2.png
https://aica.pages.dev/creators/n75242/monstermash_anyv3/1_0_0/3.png
https://aica.pages.dev/creators/n75242/monstermash_anyv3/1_0_0/4.png


text:
https://aica.pages.dev/creators/basunat/cinematic_diffusion/1_0_0/1.png
https://aica.pages.dev/creators/basunat/cinematic_diffusion/1_0_0/2.png
https://aica.pages.dev/creators/basunat/cinematic_diffusion/1_0_0/3.png
https://aica.pages.dev/creators/basunat/cinematic_diffusion/1_0_0/4.png


text:
https://aica.pages.dev/creators/runwayml/stable_diffusion/1_5_0/1.png
https://aica.pages.dev/creators/runwayml/stable_diffusion/1_5_0/2.png
https://aica.pages.dev/creators/runwayml/stable_diffusion/1_5_0/3.png
https://aica.pages.dev/creators/runwayml/stable_diffusion/1_5_0/4.png


text:
https://aica.pages.dev/creators/runwayml/stable_diffusion_inpainting/1_0_0/1.png
https://aica.pages.dev/creators/runwayml/stable_diffusion_inpainting/1_0_0/2.png
https://aica.pages.dev/creators/runwayml/stable_diffusion_inpainting/1_0_0/3.png
https://aica.pages.dev/creators/runwayml/stable_diffusion_inpainting/1_0_0/4.png


text:
https://aica.pages.dev/creators/xpuc_t/deliberate/1_0_0/1.png
https://aica.pages.dev/creators/xpuc_t/deliberate/1_0_0/2.png
https://aica.pages.dev/creators/xpuc_t/deliberate/1_0_0/3.png
https://aica.pages.dev/creators/xpuc_t/deliberate/1_0_0/4.png


text:
https://huggingface.co/ckpt/yohan-diffusion/resolve/main/yohan-diffusion.ckpt
https://huggingface.co/ckpt/yohan-diffusion/resolve/main/Cocoa.ckpt


text:
https://aica.pages.dev/creators/andite/yohan_diffusion/1_0_0/1.png
https://aica.pages.dev/creators/andite/yohan_diffusion/1_0_0/2.png
https://aica.pages.dev/creators/andite/yohan_diffusion/1_0_0/3.png
https://aica.pages.dev/creators/andite/yohan_diffusion/1_0_0/4.png


text:
https://huggingface.co/ckpt/anything-v4.0/resolve/main/anything-v4.0-pruned.ckpt
https://huggingface.co/ckpt/anything-v4.0/resolve/main/anything-v4.5-pruned.ckpt


text:
https://aica.pages.dev/creators/andite/anything/4_0_0/1.png
https://aica.pages.dev/creators/andite/anything/4_0_0/2.png
https://aica.pages.dev/creators/andite/anything/4_0_0/3.png
https://aica.pages.dev/creators/andite/anything/4_0_0/4.png


text:
https://aica.pages.dev/creators/ogkalu/illustration_diffusion/1_0_0/1.png
https://aica.pages.dev/creators/ogkalu/illustration_diffusion/1_0_0/2.png
https://aica.pages.dev/creators/ogkalu/illustration_diffusion/1_0_0/3.png
https://aica.pages.dev/creators/ogkalu/illustration_diffusion/1_0_0/4.png


text:
https://aica.pages.dev/creators/ogkalu/comic_diffusion/2_0_0/1.png
https://aica.pages.dev/creators/ogkalu/comic_diffusion/2_0_0/2.png
https://aica.pages.dev/creators/ogkalu/comic_diffusion/2_0_0/3.png
https://aica.pages.dev/creators/ogkalu/comic_diffusion/2_0_0/4.png


text:
charliebo artstyle
holliemengert artstyle
marioalberti artstyle
pepelarraz artstyle
andreasrocha artstyle
jamesdaly artstyle


text:
https://aica.pages.dev/creators/alexds9/babes/1_0_0/1.png
https://aica.pages.dev/creators/alexds9/babes/1_0_0/2.png
https://aica.pages.dev/creators/alexds9/babes/1_0_0/3.png
https://aica.pages.dev/creators/alexds9/babes/1_0_0/4.png


text:
https://aica.pages.dev/creators/astralite_heart/pony_diffusion/2_0_0/1.png
https://aica.pages.dev/creators/astralite_heart/pony_diffusion/2_0_0/2.png
https://aica.pages.dev/creators/astralite_heart/pony_diffusion/2_0_0/3.png
https://aica.pages.dev/creators/astralite_heart/pony_diffusion/2_0_0/4.png


text:
https://aica.pages.dev/creators/lucetepolis/mare_coloris/1_0_0/1.png
https://aica.pages.dev/creators/lucetepolis/mare_coloris/1_0_0/2.png
https://aica.pages.dev/creators/lucetepolis/mare_coloris/1_0_0/3.png
https://aica.pages.dev/creators/lucetepolis/mare_coloris/1_0_0/4.png


text:
https://aica.pages.dev/creators/junjuice0/voxo/1_0_0/1.png
https://aica.pages.dev/creators/junjuice0/voxo/1_0_0/2.png
https://aica.pages.dev/creators/junjuice0/voxo/1_0_0/3.png
https://aica.pages.dev/creators/junjuice0/voxo/1_0_0/4.png


text:
https://aica.pages.dev/creators/evgk_132410/realistic_vision/1_3_0/1.png
https://aica.pages.dev/creators/evgk_132410/realistic_vision/1_3_0/2.png
https://aica.pages.dev/creators/evgk_132410/realistic_vision/1_3_0/3.png
https://aica.pages.dev/creators/evgk_132410/realistic_vision/1_3_0/4.png


text:
https://aica.pages.dev/creators/syaimu/7th_layer/1_0_0/1.png
https://aica.pages.dev/creators/syaimu/7th_layer/1_0_0/2.png
https://aica.pages.dev/creators/syaimu/7th_layer/1_0_0/3.png
https://aica.pages.dev/creators/syaimu/7th_layer/1_0_0/4.png


text:
https://aica.pages.dev/creators/gsdf/counterfeit/2_0_0/1.png
https://aica.pages.dev/creators/gsdf/counterfeit/2_0_0/2.png
https://aica.pages.dev/creators/gsdf/counterfeit/2_0_0/3.png
https://aica.pages.dev/creators/gsdf/counterfeit/2_0_0/4.png


text:
https://aica.pages.dev/creators/envvi/inkpunk_diffusion/1_0_0/1.png
https://aica.pages.dev/creators/envvi/inkpunk_diffusion/1_0_0/2.png
https://aica.pages.dev/creators/envvi/inkpunk_diffusion/1_0_0/3.png
https://aica.pages.dev/creators/envvi/inkpunk_diffusion/1_0_0/4.png


text:
https://aica.pages.dev/creators/its_jay_qz/synthwave_punk/2_0_0/1.png
https://aica.pages.dev/creators/its_jay_qz/synthwave_punk/2_0_0/2.png
https://aica.pages.dev/creators/its_jay_qz/synthwave_punk/2_0_0/3.png
https://aica.pages.dev/creators/its_jay_qz/synthwave_punk/2_0_0/4.png


text:
snthwve style
nvinkpunk


text:
https://aica.pages.dev/creators/sentet1c/rando_mix3/1_0_0/1.png
https://aica.pages.dev/creators/sentet1c/rando_mix3/1_0_0/2.png
https://aica.pages.dev/creators/sentet1c/rando_mix3/1_0_0/3.png
https://aica.pages.dev/creators/sentet1c/rando_mix3/1_0_0/4.png


text:
https://aica.pages.dev/creators/chilon249/yiffy_mix/1_0_0/1.png
https://aica.pages.dev/creators/chilon249/yiffy_mix/1_0_0/2.png
https://aica.pages.dev/creators/chilon249/yiffy_mix/1_0_0/3.png
https://aica.pages.dev/creators/chilon249/yiffy_mix/1_0_0/4.png


text:
https://aica.pages.dev/creators/josephus_cheung/a_certainty/1_0_0/1.png
https://aica.pages.dev/creators/josephus_cheung/a_certainty/1_0_0/2.png
https://aica.pages.dev/creators/josephus_cheung/a_certainty/1_0_0/3.png
https://aica.pages.dev/creators/josephus_cheung/a_certainty/1_0_0/4.png


text:
https://aica.pages.dev/creators/josephus_cheung/a_certain_model/1_0_0/1.png
https://aica.pages.dev/creators/josephus_cheung/a_certain_model/1_0_0/2.png
https://aica.pages.dev/creators/josephus_cheung/a_certain_model/1_0_0/3.png
https://aica.pages.dev/creators/josephus_cheung/a_certain_model/1_0_0/4.png


text:
https://aica.pages.dev/creators/josephus_cheung/a_certain_thing/1_0_0/1.png
https://aica.pages.dev/creators/josephus_cheung/a_certain_thing/1_0_0/2.png
https://aica.pages.dev/creators/josephus_cheung/a_certain_thing/1_0_0/3.png
https://aica.pages.dev/creators/josephus_cheung/a_certain_thing/1_0_0/4.png


text:
https://aica.pages.dev/creators/comp_vis/stable_diffusion_original/1_4_0/1.png
https://aica.pages.dev/creators/comp_vis/stable_diffusion_original/1_4_0/2.png
https://aica.pages.dev/creators/comp_vis/stable_diffusion_original/1_4_0/3.png
https://aica.pages.dev/creators/comp_vis/stable_diffusion_original/1_4_0/4.png


text:
https://huggingface.co/ckpt/SimpMaker-3K1/resolve/main/SimpMaker%203k.ckpt
https://huggingface.co/ckpt/SimpMaker-3K1/resolve/main/SimpMaker%203k1.ckpt
https://huggingface.co/ckpt/SimpMaker-3K1/resolve/main/SimpMaker%203k2.ckpt
https://huggingface.co/ckpt/SimpMaker-3K1/resolve/main/SimpMaker%203k3.ckpt


text:
https://aica.pages.dev/creators/amethyst_vera/simp_maker_3k1/1_0_0/1.png
https://aica.pages.dev/creators/amethyst_vera/simp_maker_3k1/1_0_0/2.png
https://aica.pages.dev/creators/amethyst_vera/simp_maker_3k1/1_0_0/3.png
https://aica.pages.dev/creators/amethyst_vera/simp_maker_3k1/1_0_0/4.png


text:
https://aica.pages.dev/creators/cafeai/cafe_instagram_sd_1_5/6_0_0/1.png
https://aica.pages.dev/creators/cafeai/cafe_instagram_sd_1_5/6_0_0/2.png
https://aica.pages.dev/creators/cafeai/cafe_instagram_sd_1_5/6_0_0/3.png
https://aica.pages.dev/creators/cafeai/cafe_instagram_sd_1_5/6_0_0/4.png


text:
https://aica.pages.dev/creators/ray_hell/popup_book_diffusion/1_0_0/1.png
https://aica.pages.dev/creators/ray_hell/popup_book_diffusion/1_0_0/2.png
https://aica.pages.dev/creators/ray_hell/popup_book_diffusion/1_0_0/3.png
https://aica.pages.dev/creators/ray_hell/popup_book_diffusion/1_0_0/4.png


text:
https://aica.pages.dev/creators/doubleyobro/yiffy_e18/1_0_0/1.png
https://aica.pages.dev/creators/doubleyobro/yiffy_e18/1_0_0/2.png
https://aica.pages.dev/creators/doubleyobro/yiffy_e18/1_0_0/3.png
https://aica.pages.dev/creators/doubleyobro/yiffy_e18/1_0_0/4.png


text:
https://aica.pages.dev/creators/aipicasso/cool_japan_diffusion/2_1_0/1.png
https://aica.pages.dev/creators/aipicasso/cool_japan_diffusion/2_1_0/2.png
https://aica.pages.dev/creators/aipicasso/cool_japan_diffusion/2_1_0/3.png
https://aica.pages.dev/creators/aipicasso/cool_japan_diffusion/2_1_0/4.png


text:
https://aica.pages.dev/creators/mehjourney_closed_ai/open_anime_journey/1_0_0/1.png
https://aica.pages.dev/creators/mehjourney_closed_ai/open_anime_journey/1_0_0/2.png
https://aica.pages.dev/creators/mehjourney_closed_ai/open_anime_journey/1_0_0/3.png
https://aica.pages.dev/creators/mehjourney_closed_ai/open_anime_journey/1_0_0/4.png


text:
https://aica.pages.dev/creators/mocker/color_bomb_mix/1_0_0/1.png
https://aica.pages.dev/creators/mocker/color_bomb_mix/1_0_0/2.png
https://aica.pages.dev/creators/mocker/color_bomb_mix/1_0_0/3.png
https://aica.pages.dev/creators/mocker/color_bomb_mix/1_0_0/4.png


text:
https://aica.pages.dev/creators/prompthero/openjourney/2_0_0/1.png
https://aica.pages.dev/creators/prompthero/openjourney/2_0_0/2.png
https://aica.pages.dev/creators/prompthero/openjourney/2_0_0/3.png
https://aica.pages.dev/creators/prompthero/openjourney/2_0_0/4.png


text:
https://aica.pages.dev/creators/prompthero/midjourney_diffusion/4_0_0/1.png
https://aica.pages.dev/creators/prompthero/midjourney_diffusion/4_0_0/2.png
https://aica.pages.dev/creators/prompthero/midjourney_diffusion/4_0_0/3.png
https://aica.pages.dev/creators/prompthero/midjourney_diffusion/4_0_0/4.png


text:
https://aica.pages.dev/creators/stabilityai/stable_diffusion_base/2_1_0/1.png
https://aica.pages.dev/creators/stabilityai/stable_diffusion_base/2_1_0/2.png
https://aica.pages.dev/creators/stabilityai/stable_diffusion_base/2_1_0/3.png
https://aica.pages.dev/creators/stabilityai/stable_diffusion_base/2_1_0/4.png


text:
https://aica.pages.dev/creators/stabilityai/stable_diffusion_base/2_0_0/1.png
https://aica.pages.dev/creators/stabilityai/stable_diffusion_base/2_0_0/2.png
https://aica.pages.dev/creators/stabilityai/stable_diffusion_base/2_0_0/3.png
https://aica.pages.dev/creators/stabilityai/stable_diffusion_base/2_0_0/4.png


text:
https://aica.pages.dev/creators/stabilityai/stable_diffusion/2_1_0/1.png
https://aica.pages.dev/creators/stabilityai/stable_diffusion/2_1_0/2.png
https://aica.pages.dev/creators/stabilityai/stable_diffusion/2_1_0/3.png
https://aica.pages.dev/creators/stabilityai/stable_diffusion/2_1_0/4.png


text:
https://aica.pages.dev/creators/stabilityai/stable_diffusion/2_0_0/1.png
https://aica.pages.dev/creators/stabilityai/stable_diffusion/2_0_0/2.png
https://aica.pages.dev/creators/stabilityai/stable_diffusion/2_0_0/3.png
https://aica.pages.dev/creators/stabilityai/stable_diffusion/2_0_0/4.png


text:
https://aica.pages.dev/creators/stabilityai/stable_diffusion_inpainting/2_0_0/1.png
https://aica.pages.dev/creators/stabilityai/stable_diffusion_inpainting/2_0_0/2.png
https://aica.pages.dev/creators/stabilityai/stable_diffusion_inpainting/2_0_0/3.png
https://aica.pages.dev/creators/stabilityai/stable_diffusion_inpainting/2_0_0/4.png


text:
https://aica.pages.dev/creators/stabilityai/stable_diffusion_depth/2_0_0/1.png
https://aica.pages.dev/creators/stabilityai/stable_diffusion_depth/2_0_0/2.png
https://aica.pages.dev/creators/stabilityai/stable_diffusion_depth/2_0_0/3.png
https://aica.pages.dev/creators/stabilityai/stable_diffusion_depth/2_0_0/4.png


text:
https://aica.pages.dev/creators/unknown/elldreths_lucid_mix/1_0_0/1.png
https://aica.pages.dev/creators/unknown/elldreths_lucid_mix/1_0_0/2.png
https://aica.pages.dev/creators/unknown/elldreths_lucid_mix/1_0_0/3.png
https://aica.pages.dev/creators/unknown/elldreths_lucid_mix/1_0_0/4.png


text:
https://aica.pages.dev/creators/unknown/f222/1_0_0/1.png
https://aica.pages.dev/creators/unknown/f222/1_0_0/2.png
https://aica.pages.dev/creators/unknown/f222/1_0_0/3.png
https://aica.pages.dev/creators/unknown/f222/1_0_0/4.png


text:
https://aica.pages.dev/creators/unknown/protogen/2_2_0/1.png
https://aica.pages.dev/creators/unknown/protogen/2_2_0/2.png
https://aica.pages.dev/creators/unknown/protogen/2_2_0/3.png
https://aica.pages.dev/creators/unknown/protogen/2_2_0/4.png


text:
https://aica.pages.dev/creators/unknown/urp/1_0_0/1.png
https://aica.pages.dev/creators/unknown/urp/1_0_0/2.png
https://aica.pages.dev/creators/unknown/urp/1_0_0/3.png
https://aica.pages.dev/creators/unknown/urp/1_0_0/4.png


text:
https://aica.pages.dev/creators/unknown/grapefruit/1_0_0/1.png
https://aica.pages.dev/creators/unknown/grapefruit/1_0_0/2.png
https://aica.pages.dev/creators/unknown/grapefruit/1_0_0/3.png
https://aica.pages.dev/creators/unknown/grapefruit/1_0_0/4.png


text:
https://aica.pages.dev/creators/unknown/iz/1_0_0/1.png
https://aica.pages.dev/creators/unknown/iz/1_0_0/2.png
https://aica.pages.dev/creators/unknown/iz/1_0_0/3.png
https://aica.pages.dev/creators/unknown/iz/1_0_0/4.png


text:
https://aica.pages.dev/creators/unknown/anything/3_0_0/1.png
https://aica.pages.dev/creators/unknown/anything/3_0_0/2.png
https://aica.pages.dev/creators/unknown/anything/3_0_0/3.png
https://aica.pages.dev/creators/unknown/anything/3_0_0/4.png


text:
https://aica.pages.dev/creators/unknown/rbm/1_0_0/1.png
https://aica.pages.dev/creators/unknown/rbm/1_0_0/2.png
https://aica.pages.dev/creators/unknown/rbm/1_0_0/3.png
https://aica.pages.dev/creators/unknown/rbm/1_0_0/4.png


text:
https://aica.pages.dev/creators/anashel/rpg/4_0_0/1.png
https://aica.pages.dev/creators/anashel/rpg/4_0_0/2.png
https://aica.pages.dev/creators/anashel/rpg/4_0_0/3.png
https://aica.pages.dev/creators/anashel/rpg/4_0_0/4.png


text:
https://aica.pages.dev/creators/wavymulder/analog_diffusion/1_0_0/1.png
https://aica.pages.dev/creators/wavymulder/analog_diffusion/1_0_0/2.png
https://aica.pages.dev/creators/wavymulder/analog_diffusion/1_0_0/3.png
https://aica.pages.dev/creators/wavymulder/analog_diffusion/1_0_0/4.png


text:
https://huggingface.co/ckpt/OrangeMixs/resolve/main/AbyssOrangeMix2_nsfw.safetensors
https://huggingface.co/ckpt/OrangeMixs/resolve/main/AbyssOrangeMix2_hard.safetensors
https://huggingface.co/ckpt/OrangeCocoaMix/resolve/main/OrangeCocoaMix2_hard.safetensors


text:
https://aica.pages.dev/creators/warrior_mama777/orange_mixs/1_0_0/1.png
https://aica.pages.dev/creators/warrior_mama777/orange_mixs/1_0_0/2.png
https://aica.pages.dev/creators/warrior_mama777/orange_mixs/1_0_0/3.png
https://aica.pages.dev/creators/warrior_mama777/orange_mixs/1_0_0/4.png


text:
https://aica.pages.dev/creators/warrior_mama777/orange_mixs/3_0_0/1.png
https://aica.pages.dev/creators/warrior_mama777/orange_mixs/3_0_0/2.png
https://aica.pages.dev/creators/warrior_mama777/orange_mixs/3_0_0/3.png
https://aica.pages.dev/creators/warrior_mama777/orange_mixs/3_0_0/4.png


text:
https://aica.pages.dev/creators/warrior_mama777/orange_mixs/2_0_0/1.png
https://aica.pages.dev/creators/warrior_mama777/orange_mixs/2_0_0/2.png
https://aica.pages.dev/creators/warrior_mama777/orange_mixs/2_0_0/3.png
https://aica.pages.dev/creators/warrior_mama777/orange_mixs/2_0_0/4.png


text:
https://aica.pages.dev/creators/hassanblend/hassanblend/1_4_0/1.png
https://aica.pages.dev/creators/hassanblend/hassanblend/1_4_0/2.png
https://aica.pages.dev/creators/hassanblend/hassanblend/1_4_0/3.png
https://aica.pages.dev/creators/hassanblend/hassanblend/1_4_0/4.png


text:
https://aica.pages.dev/creators/closertodeath/dpepmkmp/1_0_0/1.png
https://aica.pages.dev/creators/closertodeath/dpepmkmp/1_0_0/2.png
https://aica.pages.dev/creators/closertodeath/dpepmkmp/1_0_0/3.png
https://aica.pages.dev/creators/closertodeath/dpepmkmp/1_0_0/4.png


text:
https://aica.pages.dev/creators/closertodeath/mouseymix/1_0_0/1.png
https://aica.pages.dev/creators/closertodeath/mouseymix/1_0_0/2.png
https://aica.pages.dev/creators/closertodeath/mouseymix/1_0_0/3.png
https://aica.pages.dev/creators/closertodeath/mouseymix/1_0_0/4.png


text:
https://aica.pages.dev/creators/dreamlike_art/dreamlike_photoreal/2_0_0/1.png
https://aica.pages.dev/creators/dreamlike_art/dreamlike_photoreal/2_0_0/2.png
https://aica.pages.dev/creators/dreamlike_art/dreamlike_photoreal/2_0_0/3.png
https://aica.pages.dev/creators/dreamlike_art/dreamlike_photoreal/2_0_0/4.png


text:
https://aica.pages.dev/creators/dreamlike_art/dreamlike_diffusion/1_0_0/1.png
https://aica.pages.dev/creators/dreamlike_art/dreamlike_diffusion/1_0_0/2.png
https://aica.pages.dev/creators/dreamlike_art/dreamlike_diffusion/1_0_0/3.png
https://aica.pages.dev/creators/dreamlike_art/dreamlike_diffusion/1_0_0/4.png


text:
https://aica.pages.dev/creators/sandro_halpo/sam_does_art/3_0_0/1.png
https://aica.pages.dev/creators/sandro_halpo/sam_does_art/3_0_0/2.png
https://aica.pages.dev/creators/sandro_halpo/sam_does_art/3_0_0/3.png
https://aica.pages.dev/creators/sandro_halpo/sam_does_art/3_0_0/4.png


text:
https://aica.pages.dev/creators/xxlmaes/vinte_protogen_mix/1_0_0/1.png
https://aica.pages.dev/creators/xxlmaes/vinte_protogen_mix/1_0_0/2.png
https://aica.pages.dev/creators/xxlmaes/vinte_protogen_mix/1_0_0/3.png
https://aica.pages.dev/creators/xxlmaes/vinte_protogen_mix/1_0_0/4.png


text:
https://aica.pages.dev/creators/pmejna/graphic_art/1_0_0/1.png
https://aica.pages.dev/creators/pmejna/graphic_art/1_0_0/2.png
https://aica.pages.dev/creators/pmejna/graphic_art/1_0_0/3.png
https://aica.pages.dev/creators/pmejna/graphic_art/1_0_0/4.png


text:
https://aica.pages.dev/creators/plasmo/woolitize/1_0_0/1.png
https://aica.pages.dev/creators/plasmo/woolitize/1_0_0/2.png
https://aica.pages.dev/creators/plasmo/woolitize/1_0_0/3.png
https://aica.pages.dev/creators/plasmo/woolitize/1_0_0/4.png


text:
https://aica.pages.dev/creators/plasmo/food_crit/1_0_0/1.png
https://aica.pages.dev/creators/plasmo/food_crit/1_0_0/2.png
https://aica.pages.dev/creators/plasmo/food_crit/1_0_0/3.png
https://aica.pages.dev/creators/plasmo/food_crit/1_0_0/4.png


text:
# -*- coding: utf-8 -*-
"""
Created on Sun Jun 17 19:59:33 2018

@author: mesut
"""
import yaml
import cv2
#assert cv2.__version__[0] == '3', 'The fisheye module requires opencv version >= 3.0.0'
import numpy as np
import glob
CHECKERBOARD = (6,9)
subpix_criteria = (cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER, 30, 0.1)
calibration_flags = cv2.fisheye.CALIB_RECOMPUTE_EXTRINSIC+cv2.fisheye.CALIB_CHECK_COND+cv2.fisheye.CALIB_FIX_SKEW
objp = np.zeros((1, CHECKERBOARD[0]*CHECKERBOARD[1], 3), np.float32)
objp[0,:,:2] = np.mgrid[0:CHECKERBOARD[0], 0:CHECKERBOARD[1]].T.reshape(-1, 2)
_img_shape = None
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.
images = glob.glob('images/*.png')
for fname in images:
    img = cv2.imread(fname)
    if _img_shape == None:
        _img_shape = img.shape[:2]
    else:
        assert _img_shape == img.shape[:2], "All images must share the same size."
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    # Chess board corners
    ret, corners = cv2.findChessboardCorners(gray, CHECKERBOARD, cv2.CALIB_CB_ADAPTIVE_THRESH+cv2.CALIB_CB_FAST_CHECK+cv2.CALIB_CB_NORMALIZE_IMAGE)
    # Image points (after refinin them)
    if ret == True:
        objpoints.append(objp)
        cv2.cornerSubPix(gray,corners,(3,3),(-1,-1),subpix_criteria)
        imgpoints.append(corners)
N_OK = len(objpoints)
K = np.zeros((3, 3))
D = np.zeros((4, 1))
rvecs = [np.zeros((1, 1, 3), dtype=np.float64) for i in range(N_OK)]
tvecs = [np.zeros((1, 1, 3), dtype=np.float64) for i in range(N_OK)]
rms, _, _, _, _ = \
    cv2.fisheye.calibrate(
        objpoints,
        imgpoints,
        gray.shape[::-1],
        K,
        D,
        rvecs,
        tvecs,
        calibration_flags,
        (cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER, 30, 1e-6)
    )
print("Found " + str(N_OK) + " valid images for calibration")
print("DIM=" + str(_img_shape[::-1]))
print("K=np.array(" + str(K.tolist()) + ")")
print("D=np.array(" + str(D.tolist()) + ")")
DIM=_img_shape[::-1]
balance=1
dim2=None
dim3=None

img = cv2.imread("images/test.png")
dim1 = img.shape[:2][::-1]  #dim1 is the dimension of input image to un-distort
assert dim1[0]/dim1[1] == DIM[0]/DIM[1], "Image to undistort needs to have same aspect ratio as the ones used in calibration"
if not dim2:
    dim2 = dim1
if not dim3:
    dim3 = dim1
scaled_K = K * dim1[0] / DIM[0]  # The values of K is to scale with image dimension.
scaled_K[2][2] = 1.0  # Except that K[2][2] is always 1.0
    # This is how scaled_K, dim2 and balance are used to determine the final K used to un-distort image. OpenCV document failed to make this clear!
new_K = cv2.fisheye.estimateNewCameraMatrixForUndistortRectify(scaled_K, D, dim2, np.eye(3), balance=balance)
map1, map2 = cv2.fisheye.initUndistortRectifyMap(scaled_K, D, np.eye(3), new_K, dim3, cv2.CV_16SC2)
undistorted_img = cv2.remap(img, map1, map2, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)

data = {'dim1': dim1,
        'dim2':dim2,
        'dim3': dim3,
        'K': np.asarray(K).tolist(),
        'D':np.asarray(D).tolist(),
        'new_K':np.asarray(new_K).tolist(),
        'scaled_K':np.asarray(scaled_K).tolist(),
        'balance':balance}

import json
with open("fisheye_calibration_data.json", "w") as f:
    json.dump(data, f)

cv2.imshow("undistorted", undistorted_img)
#img2 = cv2.imread("2.png")
#cv2.imshow("none undistorted", img2)
cv2.waitKey(0)
cv2.destroyAllWindows()

repo_name: kostecky/VBT-Barbell-Tracker

repo_language: Python


text:
import cv2
import numpy as np

def nothing(x):
    pass

# Load image
image = cv2.imread('2.png')

# Create a window
cv2.namedWindow('image')

# Create trackbars for color change
# Hue is from 0-179 for Opencv
cv2.createTrackbar('HMin', 'image', 0, 179, nothing)
cv2.createTrackbar('SMin', 'image', 0, 255, nothing)
cv2.createTrackbar('VMin', 'image', 0, 255, nothing)
cv2.createTrackbar('HMax', 'image', 0, 179, nothing)
cv2.createTrackbar('SMax', 'image', 0, 255, nothing)
cv2.createTrackbar('VMax', 'image', 0, 255, nothing)

# Set default value for Max HSV trackbars
cv2.setTrackbarPos('HMax', 'image', 179)
cv2.setTrackbarPos('SMax', 'image', 255)
cv2.setTrackbarPos('VMax', 'image', 255)

# Initialize HSV min/max values
hMin = sMin = vMin = hMax = sMax = vMax = 0
phMin = psMin = pvMin = phMax = psMax = pvMax = 0

while(1):
    # Get current positions of all trackbars
    hMin = cv2.getTrackbarPos('HMin', 'image')
    sMin = cv2.getTrackbarPos('SMin', 'image')
    vMin = cv2.getTrackbarPos('VMin', 'image')
    hMax = cv2.getTrackbarPos('HMax', 'image')
    sMax = cv2.getTrackbarPos('SMax', 'image')
    vMax = cv2.getTrackbarPos('VMax', 'image')

    # Set minimum and maximum HSV values to display
    lower = np.array([hMin, sMin, vMin])
    upper = np.array([hMax, sMax, vMax])

    # Convert to HSV format and color threshold
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    mask = cv2.inRange(hsv, lower, upper)
    result = cv2.bitwise_and(image, image, mask=mask)

    # Print if there is a change in HSV value
    if((phMin != hMin) | (psMin != sMin) | (pvMin != vMin) | (phMax != hMax) | (psMax != sMax) | (pvMax != vMax) ):
        print("(hMin = %d , sMin = %d, vMin = %d), (hMax = %d , sMax = %d, vMax = %d)" % (hMin , sMin , vMin, hMax, sMax , vMax))
        phMin = hMin
        psMin = sMin
        pvMin = vMin
        phMax = hMax
        psMax = sMax
        pvMax = vMax

    # Display result image
    cv2.imshow('image', result)
    if cv2.waitKey(10) & 0xFF == ord('q'):
        break

cv2.destroyAllWindows()


text:
imutils==0.5.3
numpy==1.17.0
opencv-python-headless==4.2.0.32
simpleaudio==1.0.4


text:
from collections import deque
import numpy as np
import argparse
import imutils
from imutils.video import FPS
import cv2
import math
import json
import simpleaudio as sa
import wave

def is_inflection(velocity, opposite_direction_is_true):
    if opposite_direction_is_true:
        if velocity < 0:
            return True
        else:
            return False
    if opposite_direction_is_true is False:
        if velocity >= 0:
            return True
        else:
            return False

def analyze_for_rep(history, reps):
    pos = 0
    first_phase = False
    second_phase = False
    concentric_first_lift = False
    displacement = 0
    first_phase_disp = 0
    second_phase_disp = 0
    velocities = []
    error = 0
    vector_threshold = 8

    print("Analyzing movement for rep...")
    # We need at least vector_threshold points to determine a direction and almost definitely many more for a complete rep
    if len(history) < 2 * vector_threshold:
        return(False, (0.0, 0.0, 0))

    # Method
    # 1. determine direction by looking at last X points
    # 2. keep reading and ensure each point matches initial direction up until inflection point
    # 3. Read all points after inflection up until next inflection or end of history
    # 4. Use criteria to determine if it's a rep
    for direction_pos in range(1, vector_threshold):
        displacement += history[-direction_pos][2]

    if displacement > 0:
        concentric_first_lift = True
    elif displacement < 0:
        concentric_first_lift = False
    else:
        # need more data to determine if it's a rep
        return(False, (0.0, 0.0, 0))

    while True:
        pos += 1

        if pos > len(history):
            break

        print(history[-pos])

        if not first_phase:
            # Count at least 1 first phase point before inflection and at least 100mm of displacement
            if is_inflection(history[-pos][2], concentric_first_lift) and first_phase_disp > 200:
                print("First Phase Displacement: {}".format(first_phase_disp))
                first_phase = True
            else:
                if is_inflection(history[-pos][2], concentric_first_lift):
                    if error > 3:
                        print("Found 3 error points that go in the opposite direction")
                        break
                    error += 1
                    continue
                else:
                    first_phase_disp += abs(history[-pos][1])
                    if concentric_first_lift:
                        velocities.append(abs(history[-pos][2]))
                    continue

        if not second_phase:
            # Count at least 1 second phase point before first inflection and 200mm of displacement
            # or we're on the last point in history
            if (is_inflection(history[-pos][2], not concentric_first_lift) and second_phase_disp > 200) or (pos == len(history) and second_phase_disp > 200):
                second_phase = True
                print("Second Phase Displacement: {}".format(second_phase_disp))
            else:
                second_phase_disp += abs(history[-pos][1])
                if not concentric_first_lift:
                    velocities.append(abs(history[-pos][2]))
                continue

        # All this criteria should give us a high probability of counting a rep
        # Move more than 100mm, difference between eccentric and concentric displacement < 200mm
        if first_phase and second_phase and abs(second_phase_disp - first_phase_disp) < 100:
            print("Found rep {}! first: {} mm, second: {} mm".format(reps + 1, first_phase_disp, second_phase_disp))
            if concentric_first_lift:
                concentric_disp = first_phase_disp
            else:
                concentric_disp = second_phase_disp

            avg_vel = sum(velocities) / len(velocities)
            peak_vel = max(velocities)
            return(True, (avg_vel, peak_vel, concentric_disp))

    return(False, (0.0, 0.0, 0))

def analyze_for_x_movement(history):
    # When there is a pause or inflection, let's check our previous points to see
    # if there is more movement in the x direction than the y.
    # This would indicate deracking/racking/setting up and we want to clear the history
    # of any small movements that would confuse the algorithm from detecting the start
    # of a rep, whether it be a concentric or eccentric first exercise.
    pos = 0
    x_displacement = 0
    y_displacement = 0

    print("Analyzing movement for large x displacement over y")

    while pos < len(history):
        x_displacement += abs(history[pos][0])
        y_displacement += abs(history[pos][1])
        pos += 1

    if (x_displacement - y_displacement) >= 0:
        return True

    return False

ap = argparse.ArgumentParser()
ap.add_argument("-v", "--video", help="path to the (optional) video file")
args = vars(ap.parse_args())

# Calibrate our camera
with open("fisheye_calibration_data.json", "r") as f:
    calibration_data = json.load(f)
    print(calibration_data)
    # Need to scale K, D, and dim
    # Dim should be 800x600
    # Original calibration used an image of 5120 × 3840 so same aspect ratio, which is good
    dim = (800, 600)
    scaled_K = np.asarray(calibration_data['K']) * dim[0] / 5120  # The values of K is to scale with image dimension.
    scaled_K[2][2] = 1.0  # Except that K[2][2] is always 1.0
    # This is how scaled_K, dim2 and balance are used to determine the final K used to un-distort image. OpenCV document failed to make this clear!
    new_K = cv2.fisheye.estimateNewCameraMatrixForUndistortRectify(scaled_K, np.asarray(calibration_data['D']), dim, np.eye(3), balance=calibration_data['balance'])
    calibration_map1, calibration_map2 = cv2.fisheye.initUndistortRectifyMap(scaled_K, np.asarray(calibration_data['D']), np.eye(3), new_K, dim, cv2.CV_16SC2)

# Different lighting conditions
# 1.png
# (hMin = 40 , sMin = 46, vMin = 0), (hMax = 86 , sMax = 88, vMax = 181)
# 2.png
# (hMin = 33 , sMin = 48, vMin = 103), (hMax = 64 , sMax = 156, vMax = 255)
greenLower = (33, 46, 80)
greenUpper = (86, 156, 255)

if not args.get("video", False):
    camera = cv2.VideoCapture(0)
else:
    camera = cv2.VideoCapture(args["video"])

# Read first image
(grabbed, frame) = camera.read()

frameCount = int(camera.get(cv2.CAP_PROP_FRAME_COUNT))
vid_fps = int(camera.get(cv2.CAP_PROP_FPS))
print(vid_fps)
# override with 25 fps
vid_fps = 25
fps = FPS().start()
points = deque(maxlen=10000)

last_x = None
last_y = None
ref_radius = None
velocity = 0.0
x_velocity = 0.0
y_velocity = 0.0
y_vector_up = False
moving = False
analyzed_rep = False
barbell_radius = 25
reps = 0
history = []
# How many milliseconds at rest until we consider it a rep?
rep_rest_threshold = 80.0
rep_rest_reset_threshold = 120000
rep_rest_time = 0.0
avg_vel = 0.0
peak_vel = 0.0
displacement = 0
avg_velocities = []
peak_velocities = []
velocity_loss_threshold = 20
in_range = True
end_set = False
colour = (0, 255, 0)
avg_velocity = 0
first_velocity = 0
avg_velocity_loss = 0

cv2.namedWindow("output", cv2.WINDOW_OPENGL)

while True:
    (grabbed, frame) = camera.read()

    if args.get("video") and not grabbed:
        break

    # video image is 2560 × 1920 = 1.3333333...
    # should be 800/600 to maintain aspect ratio
    frame = imutils.resize(frame, width=800)

    # Remove barrel/fisheye distortion
    frame = cv2.remap(frame, calibration_map1, calibration_map2, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)

    # Crop the frame to get rid of the deadspace from undistorting it
    frame = frame[100:500, 100:700]
    frame = imutils.resize(frame, width=800)

    im_height, im_width, _ = frame.shape

    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    mask = cv2.inRange(hsv, greenLower, greenUpper)
    mask = cv2.erode(mask, None, iterations=2)
    mask = cv2.dilate(mask, None, iterations=2)

    cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]
    center = None

    # Our barbell end is 5cm in diameter
    # fps = camera.get(cv2.CAP_PROP_FPS)
    # Each frame is 1/fps seconds in length
    # 1. Calculate the pixel distance between last position and current position. That provides pixels travelled in 1/FPS seconds.
    # That gives pixel distance between frames
    # 2. How many pixels does the circle diameter occupy? Divide by 50mm and we get pixels/mm. Invert and we get mm/pixel
    # Multiply 1 by 2 and we get instantaneous mm/s every 1/FPS

    if len(cnts) > 0:
        c = max(cnts, key=cv2.contourArea)
        ((x, y), radius) = cv2.minEnclosingCircle(c)

        if last_x is None:
            last_x = x
            last_y = y

        velocity = 0
        y_velocity = 0
        rep = False
        if reps == 0:
            in_range = True
            avg_velocity = 0
            peak_velocity = 0
            avg_velocity_loss = 0
            peak_velocity_loss = 0
            end_set = False
            colour = (0, 255, 0)

        if radius / im_height > 0.0125:
            # Take the first radius as the reference radius as it's stationary and most accurately represents dimensions
            if ref_radius is None:
                ref_radius = radius
                mmpp = barbell_radius / ref_radius
                print("ref_radius: {:.2f}, mmpp: {:.2f}".format(ref_radius, mmpp))
            x_disp = last_x - x
            y_disp = last_y - y
            y_distance = y_disp * mmpp
            x_distance = x_disp * mmpp
            distance = math.sqrt(x_disp ** 2 + y_disp ** 2) * mmpp
            if abs(y_distance) > barbell_radius / 4:
                moving = True
                analyzed_rep = False
                velocity = distance * vid_fps / 1000
                y_velocity = y_distance * vid_fps / 1000
                rep_rest_time = 0.0
                if y_velocity < 0.01 and y_velocity > -0.01:
                    moving = False
                    y_velocity = 0
                    rep_rest_time += 1 / vid_fps * 1000
                print("distance: {} mm, velocity: {:.2f} m/s, x_dist: {} mm, y_dist: {} mm, y_vel: {:.2f} m/s".format(int(distance), float(velocity), int(x_distance), int(y_distance), float(y_velocity)))
                history.append((int(x_distance), int(y_distance), y_velocity))
                if (y_velocity > 0 and y_vector_up is False) or (y_velocity < 0 and y_vector_up is True):
                    y_vector_up = not y_vector_up
                    (rep, ret) = analyze_for_rep(history, reps)
            else:
                # Only log 0 once
                if moving is True:
                    history.append((0, 0, 0))
                moving = False
                # Count how many milliseconds we're at 0 velocity
                rep_rest_time += 1 / vid_fps * 1000
                # analyze for last rep when we appear to rest for a threshold time
                if (rep_rest_time > rep_rest_threshold) and not analyzed_rep:
                    analyzed_rep = True
                    if analyze_for_x_movement(history):
                        print("Detected significant x movement over y, resetting history...")
                        history = []
                    (rep, ret) = analyze_for_rep(history, reps)

            if rep:
                history = []
                reps += 1
                avg_velocities.append(ret[0])
                peak_velocities.append(ret[1])
                displacement = ret[2]

                if reps == 1:
                    avg_velocity = avg_velocities[0]
                    peak_velocity = peak_velocities[0]
                    first_velocity = avg_velocity
                    if avg_velocity > 0.5:
                        in_range = True
                        wave_read = wave.open('good.wav', 'rb')
                    else:
                        in_range = False
                        wave_read = wave.open('bad.wav', 'rb')
                else:
                    avg_velocity = avg_velocities[-1]
                    peak_velocity = peak_velocities[-1]
                    avg_velocity_loss = (avg_velocities[0] - avg_velocities[-1]) / avg_velocities[0] * 100
                    peak_velocity_loss = (peak_velocities[0] - peak_velocities[-1]) / peak_velocities[0] * 100

                    if avg_velocity_loss > velocity_loss_threshold:
                        end_set = True
                        wave_read = wave.open('bad.wav', 'rb')
                        colour = (0, 0, 255)
                    else:
                        end_set = False
                        wave_read = wave.open('good.wav', 'rb')
                        colour = (0, 255, 0)

                audio_data = wave_read.readframes(wave_read.getnframes())
                num_channels = wave_read.getnchannels()
                bytes_per_sample = wave_read.getsampwidth()
                sample_rate = wave_read.getframerate()
                wave_obj = sa.WaveObject(audio_data, num_channels, bytes_per_sample, sample_rate)
                play_obj = wave_obj.play()

            last_x = x
            last_y = y
            cv2.circle(frame, (int(x), int(y)), int(ref_radius), (0, 255, 255), 2)
            path_color = (0, 255, 255)
            center = (int(x), int(y))
            points.appendleft(center)
            for i in range(1, len(points)):
                if points[i - 1] is None or points[i] is None:
                    continue
                cv2.line(frame, points[i - 1], points[i], path_color, 2)

    cur_frame = camera.get(cv2.CAP_PROP_POS_FRAMES)
    fps.update()
    fps.stop()
    info = [
        ("First set above 0.5 m/s", "{}".format(in_range), (0, 255, 0)),
        ("First set velocity", "{:.2f} m/s".format(first_velocity), (0, 255, 0)),
        ("Last AVG Con Velocity", "{:.2f} m/s".format(avg_velocity), (0, 255, 0)),
#        ("Last PEAK Con Velocity", "{:.2f} m/s".format(peak_velocity), (0, 255, 0)),
        ("Last Displacement", "{:.2f} mm".format(displacement), (0, 255, 0)),
        ("AVG Velocity Loss", "{:.2f} %".format(avg_velocity_loss), (0, 255, 0)),
#        ("PEAK Velocity Loss", "{:.2f} %".format(peak_velocity_loss), (0, 255, 0)),
        ("Reps", "{}".format(reps), (0, 255, 0)),
#        ("FPS", "{:.2f}".format(fps.fps()), (0, 255, 0)),
#        ("Y Velocity", "{:.2f} m/s".format(y_velocity), (0, 255, 0)),
        ("END SET", "{}".format(end_set), colour),
    ]

    # loop over the info tuples and draw them on our frame
    for (i, (k, v, c)) in enumerate(info):
        text = "{}: {}".format(k, v)
        cv2.putText(frame, text, (10, im_height - ((i * 40) + 20)),
                    cv2.FONT_HERSHEY_SIMPLEX, 1.5, c, 2)

    cv2.imshow("output", frame)
    cv2.resizeWindow("output", (1500, 1000))
    # cv2.imshow("Mask", mask)

    key = cv2.waitKey(1) & 0xFF

    if key == ord("q"):
        break
    elif key == ord("r") or (rep_rest_time > rep_rest_reset_threshold):
        reps = 0
        avg_velocities = []
        first_velocity = 0
        peak_velocities = []
        points.clear()
        rep_rest_time = 0.0

camera.release()
cv2.destroyAllWindows()


text:
# VBT-Barbell-Tracker
A proof of concept app to optically track a barbell through its range of motion using OpenCV to give the lifter realtime feedback on concentric avg velocity, cutoff velocity, and displacement for a Velocity Based Training program.

![Demo](/images/demo.gif?raw=true "Squat Demo")

## How it works
The app will detect a solid green area painted on to the end of your barbell. Given the measured diameter of this circle it will determine the pixel per mm scale to calculate distances and velocities of the barbell.

Movement of the barbell is continuously scanned to see if a lift is happening. When it detects a rep, it displays the most commonly referenced VBT metrics and informs you if your lifts are within 0.5-0.75 m/s as well as if they fall below a 20% velocity cutoff. There is an audible signal that is played of your lifts comply or fall outside of the range so you know when to terminate your set without having to keep your eyes on the computer.

The display tells you what rep you're on, the displacement of the bar, the velocity of the concentric part of the lift and whether the art should be terminated.

Once the barbell is at rest for 2 minutes, the counters and path tracking reset. You can also reset it by hand by pressing 'r'

## Motivation

- Optimize workouts by taking meaningful measurements, getting live feedback, and putting in minimum effective effort
- Autoregulation of load-volume
- Injury reduction
- Initial exposure to OpenCV and optical processing
- Initial exposure to training CNNs
- Avoid the purchase of a hardware unit like openbarbell, push, etc.

## Journey

- Started off wanting the app to auto-detect a wide variety of barbells in generalized surroundings
- Spent a week playing with Google Colab and training CNNs to do so. Moderate success, lots of GPU power needed and way too slow for running on CPU only devices
- Spent time playing with many different tracking models in OpenCV. None were reliable in a variety of scenarios.
- Realized that tracking a differentiated colour and shape was very fast, didn't require a GPU and was orders of magnitude more reliable than any tracking algorithm. Simple wins with a bit more initial setup, but it was worth it.

## VBT
https://www.scienceforsport.com/velocity-based-training

## Requirements
- Python 3.7
- A webcam or IP camera that supports RTSP
- Lime Green paper/paint/etc.

## Installation

1. Create a new python 3.7 virtualenv
```
mkvirtualenv VBT-barbell-tracker
```

2. Install python requirements
```
pip install -r requirements.txt
```

3. Generate intrinsic camera values to undistort fisheye/barrel effect
Generate intrinsic camera distortion values to remove any barrel/fisheye distortion that your camera may have. You can easily spot this by looking at the outer perimeter of your camera to see if straight lines appear curved.

    a. Using your webcam, take 10 or more snapshots of the chessboard printout. Save the images as `.png` files. Adhere the printout to a board, so it's very flat. The images should be taken to ensure you cover all areas of your image plane, paying attention to the outer perimeter where most of the distortion will take place. You can find the opencv chessboard image here: https://github.com/opencv/opencv/blob/master/doc/pattern.png

    b. Place these images in the `./images/` directory

    c. Take another image of the area you want to undistort as a test. Save it as `test.png` and place it in the `./images/` directory.

    d. Run the `python undistort_fisheye.py` script to discover the intrinsict values. They will be dumped out in a json file called `fisheye_calibration_data.json`

4. Place lime green paper/paint/etc. on the end of the barbell that faces the camera, ensuring that it covers the entire face of it. Then, take a measurement of the diameter of the face of the barbell end you covered. Mine comes out to 50mm, so the radius would be 25mm. This is **essential** to calibrating the distance scale within the app. You can use any colour you want, but you will have to adjust parameters accordingly. The idea here is to use a colour that is highly differentiated from anything being captured in your surroundings or your clothing.

## Usage

```
workon VBT-barbell-tracker
```

### Running it on a video
```
python vbt_barbell_tracker.py --video press.mp4
```

### Running it with your webcam
```
python VBT-barbell-tracker.py
```

### Running it on a RTSP stream
```
python VBT-barbell-tracker.py --video 'rtsp://USER:PASSWORD@192.168.1.127?tcp'
```

## Hotkeys

`r` Clear set and reset all counters and bar tracker. This also happens automatically after 2 minutes of no movement.

## Roadmap
- [ ] Refactor POC
- [ ] Use QT or simpleGUI to reformulate into a proper app with input/output to adjust parameters on the fly


text:
[package]
name = "winapi-util"
version = "0.1.5"  #:version
authors = ["Andrew Gallant <jamslam@gmail.com>"]
description = "A dumping ground for high level safe wrappers over winapi."
documentation = "https://docs.rs/winapi-util"
homepage = "https://github.com/BurntSushi/winapi-util"
repository = "https://github.com/BurntSushi/winapi-util"
readme = "README.md"
keywords = ["windows", "winapi", "util", "win"]
license = "Unlicense/MIT"
categories = ["os::windows-apis", "external-ffi-bindings"]
edition = "2018"

[target.'cfg(windows)'.dependencies.winapi]
version = "0.3"
features = [
  "std",
  "consoleapi",
  "errhandlingapi",
  "fileapi",
  "minwindef",
  "processenv",
  "winbase",
  "wincon",
  "winerror",
  "winnt",
]

[package.metadata.docs.rs]
targets = ["x86_64-pc-windows-msvc"]

repo_name: BurntSushi/winapi-util

repo_language: Rust


text:
max_width = 79
use_small_heuristics = "max"


text:
This project is dual-licensed under the Unlicense and MIT licenses.

You may use this code under the terms of either license.


text:
winapi-util
===========
This crate provides a smattering of safe wrappers around various parts of the
[winapi](https://crates.io/crates/winapi) crate.

[![Build status](https://github.com/BurntSushi/winapi-util/workflows/ci/badge.svg)](https://github.com/BurntSushi/winapi-util/actions)
[![](http://meritbadge.herokuapp.com/winapi-util)](https://crates.io/crates/winapi-util)

Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).

### Documentation

https://docs.rs/winapi-util

### Usage

Add this to your `Cargo.toml`:

```toml
[dependencies]
winapi-util = "0.1"
```

### Notes

This crate was born out of frustration with having to write lots of little
ffi utility bindings in a variety of crates in order to get Windows support.
Eventually, I started needing to copy & paste a lot of those utility routines.
Since they are utility routines, they often don't make sense to expose directly
in the crate in which they are defined. Instead of continuing this process,
I decided to make a crate instead.

Normally, I'm not a huge fan of "utility" crates like this that don't have a
well defined scope, but this is primarily a practical endeavor to make it
easier to isolate Windows specific ffi code.

While I don't have a long term vision for this crate, I will welcome additional
PRs that add more high level routines/types on an as-needed basis.

**WARNING:** I am not a Windows developer, so extra review to make sure I've
got things right is most appreciated.

### Minimum Rust version policy

This crate's minimum supported `rustc` version is `1.34.0`.

The current policy is that the minimum Rust version required to use this crate
can be increased in non-breaking version updates. For example, if `crate 1.0`
requires Rust 1.20.0, then `crate 1.0.z` for all values of `z` will also
require Rust 1.20.0 or newer. However, `crate 1.y` for `y > 0` may require a
newer minimum version of Rust.

In general, this crate will be conservative with respect to the minimum
supported version of Rust.


text:
name: ci
on:
  pull_request:
  push:
    branches:
    - master
  schedule:
  - cron: '00 01 * * *'
jobs:
  test:
    name: test
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        build:
        - pinned
        - stable
        - beta
        - nightly
        - win-gnu
        - linux
        - macos
        include:
        - build: pinned
          os: windows-2019
          rust: 1.34.0
        - build: stable
          os: windows-2019
          rust: stable
        - build: beta
          os: windows-2019
          rust: beta
        - build: nightly
          os: ubuntu-18.04
          rust: nightly
        - build: win-gnu
          os: windows-2019
          rust: stable-x86_64-gnu
        - build: linux
          os: ubuntu-18.04
          rust: stable
        - build: macos
          os: macos-latest
          rust: stable
    steps:
    - name: Checkout repository
      uses: actions/checkout@v2
      with:
        fetch-depth: 1
    - name: Install Rust
      uses: hecrj/setup-rust-action@v1
      with:
        rust-version: ${{ matrix.rust }}
    - run: cargo build --verbose
    - run: cargo doc --verbose
    - run: cargo test --verbose

  rustfmt:
    name: rustfmt
    runs-on: ubuntu-18.04
    steps:
    - name: Checkout repository
      uses: actions/checkout@v2
      with:
        fetch-depth: 1
    - name: Install Rust
      uses: hecrj/setup-rust-action@v1
      with:
        rust-version: stable
    - name: Install rustfmt
      run: rustup component add rustfmt
    - name: Check formatting
      run: |
        cargo fmt --all -- --check


text:
use std::fs::File;
use std::io;
use std::os::windows::io::{
    AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle,
};
use std::path::Path;
use std::process;

/// A handle represents an owned and valid Windows handle to a file-like
/// object.
///
/// When an owned handle is dropped, then the underlying raw handle is closed.
/// To get a borrowed handle, use `HandleRef`.
#[derive(Debug)]
pub struct Handle(File);

impl AsRawHandle for Handle {
    fn as_raw_handle(&self) -> RawHandle {
        self.0.as_raw_handle()
    }
}

impl FromRawHandle for Handle {
    unsafe fn from_raw_handle(handle: RawHandle) -> Handle {
        Handle(File::from_raw_handle(handle))
    }
}

impl IntoRawHandle for Handle {
    fn into_raw_handle(self) -> RawHandle {
        self.0.into_raw_handle()
    }
}

impl Handle {
    /// Create an owned handle to the given file.
    ///
    /// When the returned handle is dropped, the file is closed.
    ///
    /// Note that if the given file represents a handle to a directory, then
    /// it is generally required that it have been opened with the
    /// [`FILE_FLAG_BACKUP_SEMANTICS`] flag in order to use it in various
    /// calls such as `information` or `typ`. To have this done automatically
    /// for you, use the `from_path_any` constructor.
    ///
    /// [`FILE_FLAG_BACKUP_SEMANTICS`]: https://docs.microsoft.com/en-us/windows/desktop/api/FileAPI/nf-fileapi-createfilea
    pub fn from_file(file: File) -> Handle {
        Handle(file)
    }

    /// Open a file to the given file path, and return an owned handle to that
    /// file.
    ///
    /// When the returned handle is dropped, the file is closed.
    ///
    /// If there was a problem opening the file, then the corresponding error
    /// is returned.
    pub fn from_path<P: AsRef<Path>>(path: P) -> io::Result<Handle> {
        Ok(Handle::from_file(File::open(path)?))
    }

    /// Like `from_path`, but supports opening directory handles as well.
    ///
    /// If you use `from_path` on a directory, then subsequent queries using
    /// that handle will fail.
    pub fn from_path_any<P: AsRef<Path>>(path: P) -> io::Result<Handle> {
        use std::fs::OpenOptions;
        use std::os::windows::fs::OpenOptionsExt;
        use winapi::um::winbase::FILE_FLAG_BACKUP_SEMANTICS;

        let file = OpenOptions::new()
            .read(true)
            .custom_flags(FILE_FLAG_BACKUP_SEMANTICS)
            .open(path)?;
        Ok(Handle::from_file(file))
    }

    /// Return this handle as a standard `File` reference.
    pub fn as_file(&self) -> &File {
        &self.0
    }

    /// Return this handle as a standard `File` mutable reference.
    pub fn as_file_mut(&mut self) -> &mut File {
        &mut self.0
    }
}

/// Represents a borrowed and valid Windows handle to a file-like object, such
/// as stdin/stdout/stderr or an actual file.
///
/// When a borrowed handle is dropped, then the underlying raw handle is
/// **not** closed. To get an owned handle, use `Handle`.
#[derive(Debug)]
pub struct HandleRef(HandleRefInner);

/// The representation of a HandleRef, on which we define a custom Drop impl
/// that avoids closing the underlying raw handle.
#[derive(Debug)]
struct HandleRefInner(Option<File>);

impl Drop for HandleRefInner {
    fn drop(&mut self) {
        self.0.take().unwrap().into_raw_handle();
    }
}

impl AsRawHandle for HandleRef {
    fn as_raw_handle(&self) -> RawHandle {
        self.as_file().as_raw_handle()
    }
}

impl Clone for HandleRef {
    fn clone(&self) -> HandleRef {
        unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
    }
}

impl HandleRef {
    /// Create a borrowed handle to stdin.
    ///
    /// When the returned handle is dropped, stdin is not closed.
    pub fn stdin() -> HandleRef {
        unsafe { HandleRef::from_raw_handle(io::stdin().as_raw_handle()) }
    }

    /// Create a handle to stdout.
    ///
    /// When the returned handle is dropped, stdout is not closed.
    pub fn stdout() -> HandleRef {
        unsafe { HandleRef::from_raw_handle(io::stdout().as_raw_handle()) }
    }

    /// Create a handle to stderr.
    ///
    /// When the returned handle is dropped, stderr is not closed.
    pub fn stderr() -> HandleRef {
        unsafe { HandleRef::from_raw_handle(io::stderr().as_raw_handle()) }
    }

    /// Create a borrowed handle to the given file.
    ///
    /// When the returned handle is dropped, the file is not closed.
    pub fn from_file(file: &File) -> HandleRef {
        unsafe { HandleRef::from_raw_handle(file.as_raw_handle()) }
    }

    /// Create a borrowed handle from the given raw handle.
    ///
    /// Note that unlike the `FromRawHandle` trait, this constructor does
    /// **not** consume ownership of the given handle. That is, when the
    /// borrowed handle created by this constructor is dropped, the underlying
    /// handle will not be closed.
    ///
    /// # Safety
    ///
    /// This is unsafe because there is no guarantee that the given raw handle
    /// is a valid handle. The caller must ensure this is true before invoking
    /// this constructor.
    pub unsafe fn from_raw_handle(handle: RawHandle) -> HandleRef {
        HandleRef(HandleRefInner(Some(File::from_raw_handle(handle))))
    }

    /// Return this handle as a standard `File` reference.
    pub fn as_file(&self) -> &File {
        (self.0).0.as_ref().unwrap()
    }

    /// Return this handle as a standard `File` mutable reference.
    pub fn as_file_mut(&mut self) -> &mut File {
        (self.0).0.as_mut().unwrap()
    }
}

/// Construct borrowed and valid Windows handles from file-like objects.
pub trait AsHandleRef {
    /// A borrowed handle that wraps the raw handle of the `Self` object.
    fn as_handle_ref(&self) -> HandleRef;

    /// A convenience routine for extracting a `HandleRef` from `Self`, and
    /// then extracting a raw handle from the `HandleRef`.
    fn as_raw(&self) -> RawHandle {
        self.as_handle_ref().as_raw_handle()
    }
}

impl<'a, T: AsHandleRef> AsHandleRef for &'a T {
    fn as_handle_ref(&self) -> HandleRef {
        (**self).as_handle_ref()
    }
}

impl AsHandleRef for Handle {
    fn as_handle_ref(&self) -> HandleRef {
        unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
    }
}

impl AsHandleRef for HandleRef {
    fn as_handle_ref(&self) -> HandleRef {
        self.clone()
    }
}

impl AsHandleRef for File {
    fn as_handle_ref(&self) -> HandleRef {
        HandleRef::from_file(self)
    }
}

impl AsHandleRef for io::Stdin {
    fn as_handle_ref(&self) -> HandleRef {
        unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
    }
}

impl AsHandleRef for io::Stdout {
    fn as_handle_ref(&self) -> HandleRef {
        unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
    }
}

impl AsHandleRef for io::Stderr {
    fn as_handle_ref(&self) -> HandleRef {
        unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
    }
}

impl AsHandleRef for process::ChildStdin {
    fn as_handle_ref(&self) -> HandleRef {
        unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
    }
}

impl AsHandleRef for process::ChildStdout {
    fn as_handle_ref(&self) -> HandleRef {
        unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
    }
}

impl AsHandleRef for process::ChildStderr {
    fn as_handle_ref(&self) -> HandleRef {
        unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) }
    }
}