diff --git a/data/spindle_multi_black/0001.png b/data/spindle_multi_black/0001.png new file mode 100644 index 0000000..2bde06e Binary files /dev/null and b/data/spindle_multi_black/0001.png differ diff --git a/data/spindle_multi_black/0002.png b/data/spindle_multi_black/0002.png new file mode 100644 index 0000000..bf63dd9 Binary files /dev/null and b/data/spindle_multi_black/0002.png differ diff --git a/data/spindle_multi_black/0003.png b/data/spindle_multi_black/0003.png new file mode 100644 index 0000000..6d823cf Binary files /dev/null and b/data/spindle_multi_black/0003.png differ diff --git a/data/spindle_multi_black/0004.png b/data/spindle_multi_black/0004.png new file mode 100644 index 0000000..02a5b2c Binary files /dev/null and b/data/spindle_multi_black/0004.png differ diff --git a/data/spindle_multi_black/0005.png b/data/spindle_multi_black/0005.png new file mode 100644 index 0000000..8eca9b8 Binary files /dev/null and b/data/spindle_multi_black/0005.png differ diff --git a/data/spindle_multi_black/0006.png b/data/spindle_multi_black/0006.png new file mode 100644 index 0000000..5385253 Binary files /dev/null and b/data/spindle_multi_black/0006.png differ diff --git a/data/spindle_multi_black/0007.png b/data/spindle_multi_black/0007.png new file mode 100644 index 0000000..542ba49 Binary files /dev/null and b/data/spindle_multi_black/0007.png differ diff --git a/data/spindle_multi_black/0008.png b/data/spindle_multi_black/0008.png new file mode 100644 index 0000000..696dfff Binary files /dev/null and b/data/spindle_multi_black/0008.png differ diff --git a/data/spindle_multi_black/0009.png b/data/spindle_multi_black/0009.png new file mode 100644 index 0000000..1d84e2c Binary files /dev/null and b/data/spindle_multi_black/0009.png differ diff --git a/data/spindle_multi_black/0010.png b/data/spindle_multi_black/0010.png new file mode 100644 index 0000000..abeaf87 Binary files /dev/null and b/data/spindle_multi_black/0010.png differ diff --git a/data/spindle_multi_black/0011.png b/data/spindle_multi_black/0011.png new file mode 100644 index 0000000..bdd09c1 Binary files /dev/null and b/data/spindle_multi_black/0011.png differ diff --git a/data/spindle_multi_black/0012.png b/data/spindle_multi_black/0012.png new file mode 100644 index 0000000..6126ca0 Binary files /dev/null and b/data/spindle_multi_black/0012.png differ diff --git a/data/spindle_multi_black/0013.png b/data/spindle_multi_black/0013.png new file mode 100644 index 0000000..9e214ee Binary files /dev/null and b/data/spindle_multi_black/0013.png differ diff --git a/data/spindle_multi_black/0014.png b/data/spindle_multi_black/0014.png new file mode 100644 index 0000000..2c65b1c Binary files /dev/null and b/data/spindle_multi_black/0014.png differ diff --git a/data/spindle_multi_black/0015.png b/data/spindle_multi_black/0015.png new file mode 100644 index 0000000..e2c58f4 Binary files /dev/null and b/data/spindle_multi_black/0015.png differ diff --git a/data/spindle_multi_black/0016.png b/data/spindle_multi_black/0016.png new file mode 100644 index 0000000..1ef1bb7 Binary files /dev/null and b/data/spindle_multi_black/0016.png differ diff --git a/data/spindle_multi_black/0017.png b/data/spindle_multi_black/0017.png new file mode 100644 index 0000000..e425793 Binary files /dev/null and b/data/spindle_multi_black/0017.png differ diff --git a/data/spindle_multi_black/0018.png b/data/spindle_multi_black/0018.png new file mode 100644 index 0000000..e4390cd Binary files /dev/null and b/data/spindle_multi_black/0018.png differ diff --git a/data/spindle_multi_black/0019.png b/data/spindle_multi_black/0019.png new file mode 100644 index 0000000..8d43d36 Binary files /dev/null and b/data/spindle_multi_black/0019.png differ diff --git a/data/spindle_multi_black/0020.png b/data/spindle_multi_black/0020.png new file mode 100644 index 0000000..370aac9 Binary files /dev/null and b/data/spindle_multi_black/0020.png differ diff --git a/data/spindle_multi_black/0021.png b/data/spindle_multi_black/0021.png new file mode 100644 index 0000000..1816e1b Binary files /dev/null and b/data/spindle_multi_black/0021.png differ diff --git a/data/spindle_multi_black/0022.png b/data/spindle_multi_black/0022.png new file mode 100644 index 0000000..f6ac479 Binary files /dev/null and b/data/spindle_multi_black/0022.png differ diff --git a/data/spindle_multi_black/0023.png b/data/spindle_multi_black/0023.png new file mode 100644 index 0000000..a424544 Binary files /dev/null and b/data/spindle_multi_black/0023.png differ diff --git a/data/spindle_multi_black/0024.png b/data/spindle_multi_black/0024.png new file mode 100644 index 0000000..47f4893 Binary files /dev/null and b/data/spindle_multi_black/0024.png differ diff --git a/data/spindle_multi_black/0025.png b/data/spindle_multi_black/0025.png new file mode 100644 index 0000000..68b3233 Binary files /dev/null and b/data/spindle_multi_black/0025.png differ diff --git a/data/spindle_multi_black/0026.png b/data/spindle_multi_black/0026.png new file mode 100644 index 0000000..ca00ee9 Binary files /dev/null and b/data/spindle_multi_black/0026.png differ diff --git a/data/spindle_multi_black/0027.png b/data/spindle_multi_black/0027.png new file mode 100644 index 0000000..0db4c96 Binary files /dev/null and b/data/spindle_multi_black/0027.png differ diff --git a/data/spindle_multi_black/0028.png b/data/spindle_multi_black/0028.png new file mode 100644 index 0000000..8ba9082 Binary files /dev/null and b/data/spindle_multi_black/0028.png differ diff --git a/data/spindle_multi_black/0029.png b/data/spindle_multi_black/0029.png new file mode 100644 index 0000000..be127b9 Binary files /dev/null and b/data/spindle_multi_black/0029.png differ diff --git a/data/spindle_multi_black/0030.png b/data/spindle_multi_black/0030.png new file mode 100644 index 0000000..36eb03a Binary files /dev/null and b/data/spindle_multi_black/0030.png differ diff --git a/data/spindle_multi_black/0031.png b/data/spindle_multi_black/0031.png new file mode 100644 index 0000000..153acd4 Binary files /dev/null and b/data/spindle_multi_black/0031.png differ diff --git a/data/spindle_multi_black/0032.png b/data/spindle_multi_black/0032.png new file mode 100644 index 0000000..1c5e677 Binary files /dev/null and b/data/spindle_multi_black/0032.png differ diff --git a/data/spindle_multi_black/0033.png b/data/spindle_multi_black/0033.png new file mode 100644 index 0000000..f01574d Binary files /dev/null and b/data/spindle_multi_black/0033.png differ diff --git a/data/spindle_multi_black/0034.png b/data/spindle_multi_black/0034.png new file mode 100644 index 0000000..62d5334 Binary files /dev/null and b/data/spindle_multi_black/0034.png differ diff --git a/data/spindle_multi_black/0035.png b/data/spindle_multi_black/0035.png new file mode 100644 index 0000000..eb5d1c2 Binary files /dev/null and b/data/spindle_multi_black/0035.png differ diff --git a/data/spindle_multi_black/0036.png b/data/spindle_multi_black/0036.png new file mode 100644 index 0000000..67690eb Binary files /dev/null and b/data/spindle_multi_black/0036.png differ diff --git a/data/spindle_multi_black/0037.png b/data/spindle_multi_black/0037.png new file mode 100644 index 0000000..e6f93d1 Binary files /dev/null and b/data/spindle_multi_black/0037.png differ diff --git a/data/spindle_multi_black/0038.png b/data/spindle_multi_black/0038.png new file mode 100644 index 0000000..b2e7a4a Binary files /dev/null and b/data/spindle_multi_black/0038.png differ diff --git a/data/spindle_multi_black/0039.png b/data/spindle_multi_black/0039.png new file mode 100644 index 0000000..9148773 Binary files /dev/null and b/data/spindle_multi_black/0039.png differ diff --git a/data/spindle_multi_black/0040.png b/data/spindle_multi_black/0040.png new file mode 100644 index 0000000..c069ce9 Binary files /dev/null and b/data/spindle_multi_black/0040.png differ diff --git a/data/spindle_multi_black/0041.png b/data/spindle_multi_black/0041.png new file mode 100644 index 0000000..fdd129b Binary files /dev/null and b/data/spindle_multi_black/0041.png differ diff --git a/data/spindle_multi_black/0042.png b/data/spindle_multi_black/0042.png new file mode 100644 index 0000000..326ae12 Binary files /dev/null and b/data/spindle_multi_black/0042.png differ diff --git a/data/spindle_multi_black/0043.png b/data/spindle_multi_black/0043.png new file mode 100644 index 0000000..e898bc3 Binary files /dev/null and b/data/spindle_multi_black/0043.png differ diff --git a/data/spindle_multi_black/0044.png b/data/spindle_multi_black/0044.png new file mode 100644 index 0000000..d2fd097 Binary files /dev/null and b/data/spindle_multi_black/0044.png differ diff --git a/data/spindle_multi_black/0045.png b/data/spindle_multi_black/0045.png new file mode 100644 index 0000000..2420eb8 Binary files /dev/null and b/data/spindle_multi_black/0045.png differ diff --git a/data/spindle_multi_black/0046.png b/data/spindle_multi_black/0046.png new file mode 100644 index 0000000..4031c14 Binary files /dev/null and b/data/spindle_multi_black/0046.png differ diff --git a/data/spindle_multi_black/0047.png b/data/spindle_multi_black/0047.png new file mode 100644 index 0000000..3214de3 Binary files /dev/null and b/data/spindle_multi_black/0047.png differ diff --git a/data/spindle_multi_black/0048.png b/data/spindle_multi_black/0048.png new file mode 100644 index 0000000..fa7d51f Binary files /dev/null and b/data/spindle_multi_black/0048.png differ diff --git a/data/spindle_multi_black/0049.png b/data/spindle_multi_black/0049.png new file mode 100644 index 0000000..33a4160 Binary files /dev/null and b/data/spindle_multi_black/0049.png differ diff --git a/data/spindle_multi_black/0050.png b/data/spindle_multi_black/0050.png new file mode 100644 index 0000000..130fb04 Binary files /dev/null and b/data/spindle_multi_black/0050.png differ diff --git a/data/spindle_multi_black/0051.png b/data/spindle_multi_black/0051.png new file mode 100644 index 0000000..ab2935d Binary files /dev/null and b/data/spindle_multi_black/0051.png differ diff --git a/data/spindle_multi_black/0052.png b/data/spindle_multi_black/0052.png new file mode 100644 index 0000000..0a6ed66 Binary files /dev/null and b/data/spindle_multi_black/0052.png differ diff --git a/data/spindle_multi_black/0053.png b/data/spindle_multi_black/0053.png new file mode 100644 index 0000000..f33a7c7 Binary files /dev/null and b/data/spindle_multi_black/0053.png differ diff --git a/data/spindle_multi_black/0054.png b/data/spindle_multi_black/0054.png new file mode 100644 index 0000000..cad3cad Binary files /dev/null and b/data/spindle_multi_black/0054.png differ diff --git a/data/spindle_multi_black/0055.png b/data/spindle_multi_black/0055.png new file mode 100644 index 0000000..c51fefc Binary files /dev/null and b/data/spindle_multi_black/0055.png differ diff --git a/data/spindle_multi_black/0056.png b/data/spindle_multi_black/0056.png new file mode 100644 index 0000000..2133a9c Binary files /dev/null and b/data/spindle_multi_black/0056.png differ diff --git a/data/spindle_multi_black/0057.png b/data/spindle_multi_black/0057.png new file mode 100644 index 0000000..8e18786 Binary files /dev/null and b/data/spindle_multi_black/0057.png differ diff --git a/data/spindle_multi_black/0058.png b/data/spindle_multi_black/0058.png new file mode 100644 index 0000000..d0da91d Binary files /dev/null and b/data/spindle_multi_black/0058.png differ diff --git a/data/spindle_multi_black/0059.png b/data/spindle_multi_black/0059.png new file mode 100644 index 0000000..feb9832 Binary files /dev/null and b/data/spindle_multi_black/0059.png differ diff --git a/data/spindle_multi_black/0060.png b/data/spindle_multi_black/0060.png new file mode 100644 index 0000000..e852111 Binary files /dev/null and b/data/spindle_multi_black/0060.png differ diff --git a/data/spindle_multi_black/0061.png b/data/spindle_multi_black/0061.png new file mode 100644 index 0000000..0abc0ae Binary files /dev/null and b/data/spindle_multi_black/0061.png differ diff --git a/data/spindle_multi_black/0062.png b/data/spindle_multi_black/0062.png new file mode 100644 index 0000000..72d0deb Binary files /dev/null and b/data/spindle_multi_black/0062.png differ diff --git a/data/spindle_multi_black/0063.png b/data/spindle_multi_black/0063.png new file mode 100644 index 0000000..fb75d77 Binary files /dev/null and b/data/spindle_multi_black/0063.png differ diff --git a/data/spindle_multi_black/0064.png b/data/spindle_multi_black/0064.png new file mode 100644 index 0000000..b26cd94 Binary files /dev/null and b/data/spindle_multi_black/0064.png differ diff --git a/data/spindle_multi_black/0065.png b/data/spindle_multi_black/0065.png new file mode 100644 index 0000000..810fc44 Binary files /dev/null and b/data/spindle_multi_black/0065.png differ diff --git a/data/spindle_multi_black/0066.png b/data/spindle_multi_black/0066.png new file mode 100644 index 0000000..6de24e3 Binary files /dev/null and b/data/spindle_multi_black/0066.png differ diff --git a/data/spindle_multi_black/0067.png b/data/spindle_multi_black/0067.png new file mode 100644 index 0000000..4e7e899 Binary files /dev/null and b/data/spindle_multi_black/0067.png differ diff --git a/data/spindle_multi_black/0068.png b/data/spindle_multi_black/0068.png new file mode 100644 index 0000000..1cada39 Binary files /dev/null and b/data/spindle_multi_black/0068.png differ diff --git a/data/spindle_multi_black/0069.png b/data/spindle_multi_black/0069.png new file mode 100644 index 0000000..2814e57 Binary files /dev/null and b/data/spindle_multi_black/0069.png differ diff --git a/data/spindle_multi_black/0070.png b/data/spindle_multi_black/0070.png new file mode 100644 index 0000000..5b85c91 Binary files /dev/null and b/data/spindle_multi_black/0070.png differ diff --git a/data/spindle_multi_black/0071.png b/data/spindle_multi_black/0071.png new file mode 100644 index 0000000..d0ff36b Binary files /dev/null and b/data/spindle_multi_black/0071.png differ diff --git a/data/spindle_multi_black/0072.png b/data/spindle_multi_black/0072.png new file mode 100644 index 0000000..e535955 Binary files /dev/null and b/data/spindle_multi_black/0072.png differ diff --git a/data/spindle_multi_black/0073.png b/data/spindle_multi_black/0073.png new file mode 100644 index 0000000..691f38a Binary files /dev/null and b/data/spindle_multi_black/0073.png differ diff --git a/data/spindle_multi_black/0074.png b/data/spindle_multi_black/0074.png new file mode 100644 index 0000000..d882e88 Binary files /dev/null and b/data/spindle_multi_black/0074.png differ diff --git a/data/spindle_multi_black/0075.png b/data/spindle_multi_black/0075.png new file mode 100644 index 0000000..cb3946f Binary files /dev/null and b/data/spindle_multi_black/0075.png differ diff --git a/data/spindle_multi_black/0076.png b/data/spindle_multi_black/0076.png new file mode 100644 index 0000000..0219fd8 Binary files /dev/null and b/data/spindle_multi_black/0076.png differ diff --git a/data/spindle_multi_black/0077.png b/data/spindle_multi_black/0077.png new file mode 100644 index 0000000..0c415b1 Binary files /dev/null and b/data/spindle_multi_black/0077.png differ diff --git a/data/spindle_multi_black/0078.png b/data/spindle_multi_black/0078.png new file mode 100644 index 0000000..aa30f21 Binary files /dev/null and b/data/spindle_multi_black/0078.png differ diff --git a/data/spindle_multi_black/0079.png b/data/spindle_multi_black/0079.png new file mode 100644 index 0000000..8a1ebf0 Binary files /dev/null and b/data/spindle_multi_black/0079.png differ diff --git a/data/spindle_multi_black/0080.png b/data/spindle_multi_black/0080.png new file mode 100644 index 0000000..c717452 Binary files /dev/null and b/data/spindle_multi_black/0080.png differ diff --git a/data/spindle_multi_black/0081.png b/data/spindle_multi_black/0081.png new file mode 100644 index 0000000..5e4c496 Binary files /dev/null and b/data/spindle_multi_black/0081.png differ diff --git a/data/spindle_multi_black/0082.png b/data/spindle_multi_black/0082.png new file mode 100644 index 0000000..554dc1c Binary files /dev/null and b/data/spindle_multi_black/0082.png differ diff --git a/data/spindle_multi_black/0083.png b/data/spindle_multi_black/0083.png new file mode 100644 index 0000000..9be512f Binary files /dev/null and b/data/spindle_multi_black/0083.png differ diff --git a/data/spindle_multi_black/0084.png b/data/spindle_multi_black/0084.png new file mode 100644 index 0000000..bd8f86b Binary files /dev/null and b/data/spindle_multi_black/0084.png differ diff --git a/data/spindle_multi_black/0085.png b/data/spindle_multi_black/0085.png new file mode 100644 index 0000000..53298a0 Binary files /dev/null and b/data/spindle_multi_black/0085.png differ diff --git a/data/spindle_multi_black/0086.png b/data/spindle_multi_black/0086.png new file mode 100644 index 0000000..edb2f69 Binary files /dev/null and b/data/spindle_multi_black/0086.png differ diff --git a/data/spindle_multi_black/0087.png b/data/spindle_multi_black/0087.png new file mode 100644 index 0000000..4cd8118 Binary files /dev/null and b/data/spindle_multi_black/0087.png differ diff --git a/data/spindle_multi_black/0088.png b/data/spindle_multi_black/0088.png new file mode 100644 index 0000000..af73f73 Binary files /dev/null and b/data/spindle_multi_black/0088.png differ diff --git a/data/spindle_multi_black/0089.png b/data/spindle_multi_black/0089.png new file mode 100644 index 0000000..92d3fb9 Binary files /dev/null and b/data/spindle_multi_black/0089.png differ diff --git a/data/spindle_multi_black/0090.png b/data/spindle_multi_black/0090.png new file mode 100644 index 0000000..c0d911a Binary files /dev/null and b/data/spindle_multi_black/0090.png differ diff --git a/data/spindle_multi_black/0091.png b/data/spindle_multi_black/0091.png new file mode 100644 index 0000000..4a0f4e8 Binary files /dev/null and b/data/spindle_multi_black/0091.png differ diff --git a/data/spindle_multi_black/0092.png b/data/spindle_multi_black/0092.png new file mode 100644 index 0000000..8ba7d7c Binary files /dev/null and b/data/spindle_multi_black/0092.png differ diff --git a/data/spindle_multi_black/0093.png b/data/spindle_multi_black/0093.png new file mode 100644 index 0000000..0361e6c Binary files /dev/null and b/data/spindle_multi_black/0093.png differ diff --git a/data/spindle_multi_black/0094.png b/data/spindle_multi_black/0094.png new file mode 100644 index 0000000..e472991 Binary files /dev/null and b/data/spindle_multi_black/0094.png differ diff --git a/data/spindle_multi_black/0095.png b/data/spindle_multi_black/0095.png new file mode 100644 index 0000000..404f6d7 Binary files /dev/null and b/data/spindle_multi_black/0095.png differ diff --git a/data/spindle_multi_black/0096.png b/data/spindle_multi_black/0096.png new file mode 100644 index 0000000..48dbdf4 Binary files /dev/null and b/data/spindle_multi_black/0096.png differ diff --git a/data/spindle_multi_black/0097.png b/data/spindle_multi_black/0097.png new file mode 100644 index 0000000..88f1e9c Binary files /dev/null and b/data/spindle_multi_black/0097.png differ diff --git a/data/spindle_multi_black/0098.png b/data/spindle_multi_black/0098.png new file mode 100644 index 0000000..c12e757 Binary files /dev/null and b/data/spindle_multi_black/0098.png differ diff --git a/data/spindle_multi_black/0099.png b/data/spindle_multi_black/0099.png new file mode 100644 index 0000000..c9d18b9 Binary files /dev/null and b/data/spindle_multi_black/0099.png differ diff --git a/data/spindle_multi_black/0100.png b/data/spindle_multi_black/0100.png new file mode 100644 index 0000000..b8d7670 Binary files /dev/null and b/data/spindle_multi_black/0100.png differ diff --git a/data/spindle_multi_black/0101.png b/data/spindle_multi_black/0101.png new file mode 100644 index 0000000..0b12c61 Binary files /dev/null and b/data/spindle_multi_black/0101.png differ diff --git a/data/spindle_multi_black/0102.png b/data/spindle_multi_black/0102.png new file mode 100644 index 0000000..2a8bff1 Binary files /dev/null and b/data/spindle_multi_black/0102.png differ diff --git a/data/spindle_multi_black/0103.png b/data/spindle_multi_black/0103.png new file mode 100644 index 0000000..34a38f2 Binary files /dev/null and b/data/spindle_multi_black/0103.png differ diff --git a/data/spindle_multi_black/0104.png b/data/spindle_multi_black/0104.png new file mode 100644 index 0000000..973e6cc Binary files /dev/null and b/data/spindle_multi_black/0104.png differ diff --git a/data/spindle_multi_black/0105.png b/data/spindle_multi_black/0105.png new file mode 100644 index 0000000..cd832dc Binary files /dev/null and b/data/spindle_multi_black/0105.png differ diff --git a/data/spindle_multi_black/0106.png b/data/spindle_multi_black/0106.png new file mode 100644 index 0000000..913e932 Binary files /dev/null and b/data/spindle_multi_black/0106.png differ diff --git a/data/spindle_multi_black/0107.png b/data/spindle_multi_black/0107.png new file mode 100644 index 0000000..5b79c40 Binary files /dev/null and b/data/spindle_multi_black/0107.png differ diff --git a/data/spindle_multi_black/0108.png b/data/spindle_multi_black/0108.png new file mode 100644 index 0000000..a05153c Binary files /dev/null and b/data/spindle_multi_black/0108.png differ diff --git a/data/spindle_multi_black/0109.png b/data/spindle_multi_black/0109.png new file mode 100644 index 0000000..fd6b945 Binary files /dev/null and b/data/spindle_multi_black/0109.png differ diff --git a/data/spindle_multi_black/0110.png b/data/spindle_multi_black/0110.png new file mode 100644 index 0000000..b28518d Binary files /dev/null and b/data/spindle_multi_black/0110.png differ diff --git a/data/spindle_multi_black/0111.png b/data/spindle_multi_black/0111.png new file mode 100644 index 0000000..7581d46 Binary files /dev/null and b/data/spindle_multi_black/0111.png differ diff --git a/data/spindle_multi_black/0112.png b/data/spindle_multi_black/0112.png new file mode 100644 index 0000000..a524b51 Binary files /dev/null and b/data/spindle_multi_black/0112.png differ diff --git a/data/spindle_multi_black/0113.png b/data/spindle_multi_black/0113.png new file mode 100644 index 0000000..3922264 Binary files /dev/null and b/data/spindle_multi_black/0113.png differ diff --git a/data/spindle_multi_black/0114.png b/data/spindle_multi_black/0114.png new file mode 100644 index 0000000..64e4060 Binary files /dev/null and b/data/spindle_multi_black/0114.png differ diff --git a/data/spindle_multi_black/0115.png b/data/spindle_multi_black/0115.png new file mode 100644 index 0000000..b489bc2 Binary files /dev/null and b/data/spindle_multi_black/0115.png differ diff --git a/data/spindle_multi_black/0116.png b/data/spindle_multi_black/0116.png new file mode 100644 index 0000000..74bcf2a Binary files /dev/null and b/data/spindle_multi_black/0116.png differ diff --git a/data/spindle_multi_black/0117.png b/data/spindle_multi_black/0117.png new file mode 100644 index 0000000..b5b7ad8 Binary files /dev/null and b/data/spindle_multi_black/0117.png differ diff --git a/data/spindle_multi_black/0118.png b/data/spindle_multi_black/0118.png new file mode 100644 index 0000000..57f4005 Binary files /dev/null and b/data/spindle_multi_black/0118.png differ diff --git a/data/spindle_multi_black/0119.png b/data/spindle_multi_black/0119.png new file mode 100644 index 0000000..f14b63d Binary files /dev/null and b/data/spindle_multi_black/0119.png differ diff --git a/data/spindle_multi_black/0120.png b/data/spindle_multi_black/0120.png new file mode 100644 index 0000000..d5eca01 Binary files /dev/null and b/data/spindle_multi_black/0120.png differ diff --git a/ocv_corner_tracker.py b/ocv_corner_tracker.py new file mode 100644 index 0000000..40a18f9 --- /dev/null +++ b/ocv_corner_tracker.py @@ -0,0 +1,65 @@ +import cv2 +import numpy as np +import imutils as im + +from util import bbox_extend, bbox_round, image_crop, to_rect, bbox_add_position, bbox_center + +IMG_SCALE_UP = 1 +IMG_ROTATE = 0 + + +class CornerTracker: + def __init__(self, reference: np.array, bbox: np.array, name: str = 'CornerTracker'): + self.ref = {'image': reference, 'bbox': bbox, 'offset': (0, 0)} + self.name = name + self._path = [] + self.line_from = None + self.first_frame = True + + def _print(self, s): + print(f"{self.name}: {s}") + + def process(self, image: np.array): + crop_scaled = im.resize(image, IMG_SCALE_UP * image.shape[1], IMG_SCALE_UP * image.shape[0]) + template = self.ref['image'] + bb_template = self.ref['bbox'] + + template_scaled = im.resize(template, IMG_SCALE_UP * template.shape[0], IMG_SCALE_UP * template.shape[1]) + matcher_res = cv2.matchTemplate(crop_scaled, template_scaled, cv2.TM_CCOEFF_NORMED) + + (min_val, max_val, min_loc, max_loc) = cv2.minMaxLoc(matcher_res) + self._print(f"(min_val, max_val, min_loc, max_loc): {(min_val, max_val, min_loc, max_loc)}") + self._print(f"matcher_res : {matcher_res.shape}") + self._print(f"crop : {image.shape}") + self._print(f"crop_scaled : {crop_scaled.shape}") + self._print(f"template : {template.shape}") + self._print(f"template_scaled : {template_scaled.shape}") + + matcher_start_x = max_loc[0]/IMG_SCALE_UP + matcher_start_y = max_loc[1]/IMG_SCALE_UP + if self.first_frame: + self.first_frame = False + offset_x = matcher_start_x - bb_template[0] + offset_y = matcher_start_y - bb_template[1] + self.ref['offset'] = (offset_x, offset_y) + self._print(f"offset : {(offset_x, offset_y)}") + + matcher_start_x -= self.ref['offset'][0] + matcher_start_y -= self.ref['offset'][1] + + self._print(f"matcher_start : {(matcher_start_x, matcher_start_y)}") + matcher_bbox_local = (round(matcher_start_x), round(matcher_start_y), template.shape[1], template.shape[0]) + + cv2.imshow(f"{self.name}: Matcher res", matcher_res) +# cv2.imshow("{self.name}: Matcher view", matcher_crop) + + return matcher_bbox_local, matcher_res + + def path_add(self, point): + if self.line_from is not None: + self._path.append({'from': self.line_from, 'to': point}) + self.line_from = point + + @property + def path(self): + return self._path diff --git a/ocv_find_corners.py b/ocv_find_corners.py index c063978..1b4aa3a 100644 --- a/ocv_find_corners.py +++ b/ocv_find_corners.py @@ -57,7 +57,7 @@ parser = argparse.ArgumentParser(description='Code for Shi-Tomasi corner detecto parser.add_argument('--input', help='Path to input image.', default='pic3.png') args = parser.parse_args() -src = cv.imread('./data/spindle_bg_black/0001.png') +src = cv.imread('./data/spindle_multi_black/0001.png') if src is None: print('Could not open or find the image:', args.input) exit(0) diff --git a/ocv_template_matching.py b/ocv_template_matching.py index 2c16264..abaff22 100644 --- a/ocv_template_matching.py +++ b/ocv_template_matching.py @@ -3,6 +3,7 @@ import sys import imutils as im from util import bbox_extend, bbox_round, image_crop, to_rect, bbox_add_position, bbox_center +from ocv_corner_tracker import CornerTracker COLOR_TRACKER = (0, 255, 0) COLOR_TRACKER_EXT = (0, 255, 255) @@ -12,7 +13,7 @@ IMG_SCALE_UP = 1 TEMPLATE_MATCH_OVERLAP = 0 #video = cv2.VideoCapture("./data/IMG_1730.MP4") -video = cv2.VideoCapture('./data/spindle/%04d.png') +video = cv2.VideoCapture('./data/spindle_multi_black/%04d.png') # Exit if video not open # d. @@ -29,8 +30,22 @@ if not ok: bb_crop = bbox_extend(cv2.selectROI("Image", image, False), TEMPLATE_MATCH_OVERLAP) crop = image_crop(image.copy(), bb_crop) -bb_template = cv2.selectROI("Image", crop, fromCenter=True, showCrosshair=True) -template = cv2.cvtColor(image_crop(crop.copy(), bb_template), cv2.COLOR_BGR2GRAY) +ct_list = [] +count = 1 +while True: + print(f"Add Corner {count}") + bb_template = cv2.selectROI("Image", crop, fromCenter=True, showCrosshair=True) + template = cv2.cvtColor(image_crop(crop.copy(), bb_template), cv2.COLOR_BGR2GRAY) + ct_list.append(CornerTracker(template, bb_template)) + print(f"Corner {count} added") + print(f"Press any key to add another corner or ESC to continue") + + k = cv2.waitKey(-1) & 0xff + if k == 27: + break + count += 1 + +print(f"Added {count} corners") # Initialize tracker with first frame and bounding box tracker = cv2.TrackerKCF().create() @@ -42,6 +57,7 @@ line_from = None is_startup = True offset_x = 0 offset_y = 1 +mode = True while True: # Read a new frame ok, image = video.read() @@ -59,66 +75,88 @@ while True: image_anno = image.copy() if ok: - # Perform template match operations - crop_scaled = im.resize(crop.copy(), IMG_SCALE_UP * crop.shape[1], IMG_SCALE_UP * crop.shape[0]) - template_scaled = im.resize(template, IMG_SCALE_UP * template.shape[0], IMG_SCALE_UP * template.shape[1]) - res = cv2.matchTemplate(crop_scaled, template_scaled, cv2.TM_CCOEFF_NORMED) - (min_val, max_val, min_loc, max_loc) = cv2.minMaxLoc(res) - print(f"(min_val, max_val, min_loc, max_loc): {(min_val, max_val, min_loc, max_loc)}") - print(f"matcher_res : {res.shape}") - print(f"crop : {crop.shape}") - print(f"crop_scaled : {crop_scaled.shape}") - print(f"template : {template.shape}") - print(f"template_scaled : {template_scaled.shape}") + if mode: + for ct in ct_list: + matcher_bbox_local, matcher = ct.process(crop) + matcher_top_left_local, matcher_bottom_right_local = to_rect(bbox_round(matcher_bbox_local)) - matcher_start_x = max_loc[0]/IMG_SCALE_UP - matcher_start_y = max_loc[1]/IMG_SCALE_UP - if is_startup: - is_startup = False - offset_x = matcher_start_x - bb_template[0] - offset_y = matcher_start_y - bb_template[1] - print(f"offset : {(offset_x, offset_y)}") + matcher_bbox = bbox_round(bbox_add_position(matcher_bbox_local, bb_crop)) + matcher_rect = to_rect(matcher_bbox) - matcher_start_x -= offset_x - matcher_start_y -= offset_y - print(f"matcher_start : {(matcher_start_x, matcher_start_y)}") - matcher_bbox_local = (round(matcher_start_x), round(matcher_start_y), template.shape[1], template.shape[0]) - matcher_top_left_local, matcher_bottom_right_local = to_rect(bbox_round(matcher_bbox_local)) + tracker_rect = to_rect(bb_crop) + template_top_left, template_bottom_right = to_rect(bb_template) - matcher_bbox = bbox_round(bbox_add_position(matcher_bbox_local, bb_crop)) - matcher_rect = to_rect(matcher_bbox) + cv2.rectangle(crop, template_top_left, template_bottom_right, COLOR_TEMPLATE, 1) + cv2.rectangle(crop, matcher_top_left_local, matcher_bottom_right_local, COLOR_MATCHER, 1) - tracker_rect = to_rect(bb_crop) - template_top_left, template_bottom_right = to_rect(bb_template) + cv2.rectangle(image_anno, matcher_rect[0], matcher_rect[1], COLOR_MATCHER, 1) + cv2.rectangle(image_anno, tracker_rect[0], tracker_rect[1], COLOR_TRACKER, 1) + matcher_crop = image_crop(image, matcher_bbox) - cv2.rectangle(crop, template_top_left, template_bottom_right, COLOR_TEMPLATE, 1) - cv2.rectangle(crop, matcher_top_left_local, matcher_bottom_right_local, COLOR_MATCHER, 1) + # Draw path + line_to = bbox_center(matcher_bbox) + ct.path_add(line_to) - cv2.rectangle(image_anno, matcher_rect[0], matcher_rect[1], COLOR_MATCHER, 1) - cv2.rectangle(image_anno, tracker_rect[0], tracker_rect[1], COLOR_TRACKER, 1) - matcher_crop = image_crop(image, matcher_bbox) + for p in ct.path: + cv2.line(image_anno, p['from'], p['to'], (0, 0, 255), 2) - # Draw path - line_to = bbox_center(matcher_bbox) - if line_from is not None: - path.append({'from': line_from, 'to': line_to}) - line_from = line_to + else: + # Perform template match operations + crop_scaled = im.resize(crop.copy(), IMG_SCALE_UP * crop.shape[1], IMG_SCALE_UP * crop.shape[0]) + template_scaled = im.resize(template, IMG_SCALE_UP * template.shape[0], IMG_SCALE_UP * template.shape[1]) + matcher_res = cv2.matchTemplate(crop_scaled, template_scaled, cv2.TM_CCOEFF_NORMED) + (min_val, max_val, min_loc, max_loc) = cv2.minMaxLoc(matcher_res) + print(f"(min_val, max_val, min_loc, max_loc): {(min_val, max_val, min_loc, max_loc)}") + print(f"matcher_res : {matcher_res.shape}") + print(f"crop : {crop.shape}") + print(f"crop_scaled : {crop_scaled.shape}") + print(f"template : {template.shape}") + print(f"template_scaled : {template_scaled.shape}") - for p in path: - cv2.line(image_anno, p['from'], p['to'], (0, 0, 255), 2) + matcher_start_x = max_loc[0]/IMG_SCALE_UP + matcher_start_y = max_loc[1]/IMG_SCALE_UP + if is_startup: + is_startup = False + offset_x = matcher_start_x - bb_template[0] + offset_y = matcher_start_y - bb_template[1] + print(f"offset : {(offset_x, offset_y)}") + + matcher_start_x -= offset_x + matcher_start_y -= offset_y + print(f"matcher_start : {(matcher_start_x, matcher_start_y)}") + matcher_bbox_local = (round(matcher_start_x), round(matcher_start_y), template.shape[1], template.shape[0]) + matcher_top_left_local, matcher_bottom_right_local = to_rect(bbox_round(matcher_bbox_local)) + + matcher_bbox = bbox_round(bbox_add_position(matcher_bbox_local, bb_crop)) + matcher_rect = to_rect(matcher_bbox) + + tracker_rect = to_rect(bb_crop) + template_top_left, template_bottom_right = to_rect(bb_template) + + cv2.rectangle(crop, template_top_left, template_bottom_right, COLOR_TEMPLATE, 1) + cv2.rectangle(crop, matcher_top_left_local, matcher_bottom_right_local, COLOR_MATCHER, 1) + + cv2.rectangle(image_anno, matcher_rect[0], matcher_rect[1], COLOR_MATCHER, 1) + cv2.rectangle(image_anno, tracker_rect[0], tracker_rect[1], COLOR_TRACKER, 1) + matcher_crop = image_crop(image, matcher_bbox) + + # Draw path + line_to = bbox_center(matcher_bbox) + if line_from is not None: + path.append({'from': line_from, 'to': line_to}) + line_from = line_to + + for p in path: + cv2.line(image_anno, p['from'], p['to'], (0, 0, 255), 2) + + cv2.imshow("Matcher res", matcher_res) + cv2.imshow("Matcher view", matcher_crop) cv2.imshow("Crop", crop) cv2.imshow("Image", image_anno) - cv2.imshow("Matcher res", res) - cv2.imshow("Matcher view", matcher_crop) - - while True: - # Exit if ESC pressed - k = cv2.waitKey(1) & 0xff - if k == 27: - break - if k == 32: - break + # Exit if ESC pressed + k = cv2.waitKey(-1) & 0xff if k == 27: break +