diff --git a/README.md b/README.md index 100cb10..717a882 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- +

The COCOpen library is a scalable and open source method of generating a labelled dataset of colored images of any object category automatically. This dataset can be used for training object instance segmentation models for a wide range of applications like manufacturing, logistics, autonomous driving, and domestic services. COCOpen uses foreground images of single objects against blank backgrounds and background images similar to backgrounds found in the target deployment environment as input. The library annotates each object with its unique category identification number, bounding box, and instance segmentation mask in the Microsoft Common Objects in Context (COCO) format [1,2]. The COCOpen-OpenCV repository uses COCOpen to generate a dataset of images comprising instances of wires and networking devices, visualizes the annotations for these images, trains an instance segmentation model, and demonstrates inference with the trained model [3,4]. diff --git a/config/config.json b/config/config.json new file mode 100644 index 0000000..06cd8c6 --- /dev/null +++ b/config/config.json @@ -0,0 +1,12 @@ +{ + "boxAppSettings": { + "clientID": "fd4km8gqqz1vazdv4gqad1uxho0mhe5v", + "clientSecret": "d5UfZJLUnd3R3Hjjp4Kp9YnVbmBwPf2B", + "appAuth": { + "publicKeyID": "w8lcnj0g", + "privateKey": "-----BEGIN ENCRYPTED PRIVATE KEY-----\nMIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIHiYmUhP4w9cCAggA\nMBQGCCqGSIb3DQMHBAiCSHdfRQ+crgSCBMiIbESQjYZahZ6TL3po2593rsSHxH12\n52KF42Pfyi1AL9MFg2sSig1povyDOCzX8DYS0VIkO+bc/OdZ9BCI5GUqn7WShV6b\nmrfLxeln/MSOcnHC3gv0IE0jp5WOXVKr4t9TZHQw22aOQeLdgB2TdKukbP6Vr2eJ\n74LZ4iFjUAhnlrh5jiDVC6Mab5EbXPmHG/fB2STHU49r8Ss/iRXhaimUIbtI5fxe\nvGJgPohc8Smj2wJ42P/kOCl7XeKbChrka9kqy3Cv4KS1EjPaaZ1sA0ol+Kw4Wdwh\nweKrGBH15xCSX+EACKoTTeRyVzJ81q/Pjnl67FTu8H1+8W/bKJtjaWNzySlVcV8b\nicxeSIfGT6KiehVPuR9FNRr1KZqvsgVqlI8xZefR8LexK4tDD8VlNgXLZaK7I0ja\n5MbaobaMXGQ/CsJQwCz/KEVT27d1LRCUgnGa25CY8GLiMefSAiAeH2wyZysRsNmk\ncmset1E/cPVWFo3oYlVQW6mqJp56RI4ZxXPtFQyjKSnlS8Ar1XXesvbbxQ5zzjNC\nh6xNR4LqPWoIorVwhUBXmyOVox4r0ivk9sRYAHayi4RcWGvIyjGKE8Damy05KRuC\nQrucFOG9L9fopiXtejoesUJ2438OSY6G88yQdL4Uvw9+s6B3GGkBJamdFMaW8rFe\nxQt8iEqb+Tdic4ODGByldoCD2TqwmQcA8t5LtVZshjk3DMAv9AwkT4FiL2Y9ivH4\nC535RoUlIqcRZU0bD4oWB+Ci3DlLEfg9gQ6OSrv/EFcGuyA7MqmBFtK+Ac99Esj/\n6K3Njn4UK5lJ1+0f3WRl3XKBDtOqC2qHluvJuLArErfa1gswJjpH7H+zFij2MN15\nyLiP6nYnalu2Pg9xT4RTlUS7mA4dBISYKVZs4s5pgaE0f+2YxABL9hLAhxKJ6Xn5\nHIGky6Ox0pDklRz3E52xbAb241uDXDhcFcEN1GH0GhPdsJPSbOlHcO3VQdRMYtqH\n3MLIJ2flFxDQWGflh7PSdN59C320Qc76kJ8FGysZgHaGrnBrcjunnqjTpAh/+Kdv\nbzLCmQd3m/JEY08c7KTVgHrJuRxU8JGbHjFyx2otOh60L8rFYihvaBAx0NSrxU8i\nOlPUunL6q6K5kLrFJ23xdUX5y8JuR65kMo+doMstu3L7wcGQqkFu4447fOoTko5j\nMZd7YoekbVR4yCwr3cHCAywzS/uNPtLQpH4KvlAX98u6Ei0bQF/f+ZGqFEHnP3Ys\nKvdM3FrDrE4X7g/m57KuE2f/7bh3fEYg3G4IGIlS0Dvvz7VyZm7FdaFfjLKLFB/8\nt0Qz7BruAI8xh4DilUG2hNJO3lMUSN1AKUyxwkxz6gILLJEQvtAGBejsjR58cvyp\nsYgz2ijvO9EXJY4JdWUxcs1h9VvzwQ4cRCJZS16vUMaIS1bAQA0U/2wT1VXGthIv\ngVS60XMU96pT62fgri7XGESGjWPU7ZTtFhHngaw3ll2ZKSokpBBPDP4BVLFKA1Jd\n9/YWV5uSPJA7U5P8ChZctAEB5OEp/uA9PNrOQNeLz+DBGBxe7ydASr1P4YHjEaxU\n60YvZP/w8D0hRTlctlJkSOwnlXjxrqewwblv347FI4wCVjlFP020T89TRKPPEQbX\nQ0Q=\n-----END ENCRYPTED PRIVATE KEY-----\n", + "passphrase": "e09acbeef430823169aff2af557d75a4" + } + }, + "enterpriseID": "83165" +} \ No newline at end of file diff --git a/config/data_environment.yaml b/config/data_environment.yaml index e6caab1..27df126 100644 --- a/config/data_environment.yaml +++ b/config/data_environment.yaml @@ -1,226 +1,95 @@ name: cocopen-data channels: - pytorch - - anaconda - conda-forge - defaults dependencies: - _libgcc_mutex=0.1=conda_forge - _openmp_mutex=4.5=2_gnu - - alsa-lib=1.2.8=h166bdaf_0 - - aom=3.5.0=h27087fc_0 - - attr=2.5.1=h166bdaf_1 - - azure-core=1.26.1=pyhd8ed1ab_0 - - azure-storage-blob=12.14.1=pyhd8ed1ab_0 - - black=22.10.0=py39hf3d152e_2 - blas=1.0=mkl - - blinker=1.5=pyhd8ed1ab_0 - - brotli=1.0.9=h166bdaf_8 - - brotli-bin=1.0.9=h166bdaf_8 - - brotlipy=0.7.0=py39hb9d737c_1005 - - bzip2=1.0.8=h7f98852_4 - - c-ares=1.18.1=h7f98852_0 - - ca-certificates=2022.12.7=ha878542_0 - - cairo=1.16.0=ha61ee94_1014 - - certifi=2022.12.7=pyhd8ed1ab_0 - - cffi=1.15.1=py39he91dace_2 - - charset-normalizer=2.1.1=pyhd8ed1ab_0 - - click=8.1.3=unix_pyhd8ed1ab_2 - - colorama=0.4.6=pyhd8ed1ab_0 - - contourpy=1.0.6=py39hf939315_0 + - bzip2=1.0.8=h7b6447c_0 + - ca-certificates=2023.7.22=hbcca054_0 + - certifi=2023.7.22=pyhd8ed1ab_0 + - colorama=0.4.6=py39h06a4308_0 - cpuonly=2.0=0 - - cryptography=38.0.4=py39h3ccb8fc_0 - cycler=0.11.0=pyhd8ed1ab_0 - - cython=0.29.32=py39h5a03fae_1 - - dbus=1.13.18=hb2f20db_0 - - expat=2.5.0=h27087fc_0 - - ffmpeg=5.1.2=gpl_h13415ed_104 - - fftw=3.3.10=nompi_hf0379b8_106 - - flake8=6.0.0=pyhd8ed1ab_0 - - font-ttf-dejavu-sans-mono=2.37=hab24e00_0 - - font-ttf-inconsolata=3.000=h77eed37_0 - - font-ttf-source-code-pro=2.038=h77eed37_0 - - font-ttf-ubuntu=0.83=hab24e00_0 - - fontconfig=2.14.1=hc2a2eb6_0 - - fonts-conda-ecosystem=1=0 - - fonts-conda-forge=1=0 - - fonttools=4.38.0=py39hb9d737c_1 - - freeglut=3.2.2=h9c3ff4c_1 - - freetype=2.12.1=hca18f0e_1 - - gettext=0.21.1=h27087fc_0 - - glib=2.74.1=h6239696_1 - - glib-tools=2.74.1=h6239696_1 - - gmp=6.2.1=h58526e2_0 - - gnutls=3.7.8=hf3e180e_0 - - graphite2=1.3.14=h295c915_1 - - gst-plugins-base=1.21.2=h3e40eee_0 - - gstreamer=1.21.2=hd4edc92_0 - - gstreamer-orc=0.4.33=h166bdaf_0 - - harfbuzz=5.3.0=h418a68e_0 - - hdf5=1.12.2=nompi_h4df4325_100 - - icu=70.1=h27087fc_0 - - idna=3.4=pyhd8ed1ab_0 - - intel-openmp=2022.1.0=h9e868ea_3769 - - isodate=0.6.1=pyhd8ed1ab_0 - - jack=1.9.21=h583fa2b_2 - - jasper=2.0.33=ha77e612_0 - - jpeg=9e=h166bdaf_2 - - keyutils=1.6.1=h166bdaf_0 - - kiwisolver=1.4.4=py39hf939315_1 - - krb5=1.19.3=h08a2579_0 - - lame=3.100=h166bdaf_1003 - - lcms2=2.14=h6ed2654_0 - - ld_impl_linux-64=2.39=hcc3a1bd_1 - - lerc=4.0.0=h27087fc_0 - - libblas=3.9.0=16_linux64_mkl - - libbrotlicommon=1.0.9=h166bdaf_8 - - libbrotlidec=1.0.9=h166bdaf_8 - - libbrotlienc=1.0.9=h166bdaf_8 - - libcap=2.66=ha37c62d_0 - - libcblas=3.9.0=16_linux64_mkl - - libclang=15.0.6=default_h2e3cab8_0 - - libclang13=15.0.6=default_h3a83d3e_0 - - libcups=2.3.3=h3e49a29_2 - - libcurl=7.86.0=h2283fc2_1 - - libdb=6.2.32=h9c3ff4c_0 - - libdeflate=1.14=h166bdaf_0 - - libdrm=2.4.114=h166bdaf_0 - - libedit=3.1.20210910=h7f8727e_0 - - libev=4.33=h516909a_1 - - libevent=2.1.10=h28343ad_4 - - libffi=3.4.2=h7f98852_5 - - libflac=1.4.2=h27087fc_0 - - libgcc-ng=12.2.0=h65d4601_19 - - libgcrypt=1.10.1=h166bdaf_0 - - libgfortran-ng=12.2.0=h69a702a_19 - - libgfortran5=12.2.0=h337968e_19 - - libglib=2.74.1=h606061b_1 - - libglu=9.0.0=he1b5a44_1001 - - libgomp=12.2.0=h65d4601_19 - - libgpg-error=1.45=hc0c96e0_0 - - libiconv=1.17=h166bdaf_0 - - libidn2=2.3.4=h166bdaf_0 - - liblapack=3.9.0=16_linux64_mkl - - liblapacke=3.9.0=16_linux64_mkl - - libllvm15=15.0.6=h63197d8_0 - - libnghttp2=1.47.0=hff17c54_1 - - libnsl=2.0.0=h7f98852_0 - - libogg=1.3.5=h27cfd23_1 - - libopenblas=0.3.21=pthreads_h78a6416_3 - - libopencv=4.6.0=py39h9757d25_6 - - libopus=1.3.1=h7f98852_1 - - libpciaccess=0.17=h166bdaf_0 - - libpng=1.6.39=h753d276_0 - - libpq=15.1=h67c24c5_1 - - libprotobuf=3.21.11=h3eb15da_0 - - libsndfile=1.1.0=hcb278e6_1 - - libsqlite=3.40.0=h753d276_0 - - libssh2=1.10.0=hf14f497_3 - - libstdcxx-ng=12.2.0=h46fd767_19 - - libsystemd0=252=h2a991cd_0 - - libtasn1=4.19.0=h166bdaf_0 - - libtiff=4.4.0=h55922b4_4 - - libtool=2.4.6=h9c3ff4c_1008 - - libudev1=252=h166bdaf_0 - - libunistring=0.9.10=h7f98852_0 - - libuuid=2.32.1=h7f98852_1000 - - libuv=1.44.2=h166bdaf_0 - - libva=2.16.0=h166bdaf_0 - - libvorbis=1.3.7=h9c3ff4c_0 - - libvpx=1.11.0=h9c3ff4c_3 - - libwebp-base=1.2.4=h166bdaf_0 - - libxcb=1.13=h7f98852_1004 - - libxkbcommon=1.0.3=he3ba5ed_0 - - libxml2=2.10.3=h7463322_0 - - libzlib=1.2.13=h166bdaf_4 - - lz4-c=1.9.3=h9c3ff4c_1 - - matplotlib-base=3.6.2=py39hf9fd14e_0 - - mccabe=0.7.0=pyhd3eb1b0_0 - - mkl=2022.1.0=hc2b9512_224 - - mpg123=1.31.1=h27087fc_0 - - msrest=0.7.1=pyhd8ed1ab_0 - - munkres=1.1.4=pyh9f0ad1d_0 - - mypy_extensions=0.4.3=py39hf3d152e_6 - - mysql-common=8.0.31=h26416b9_0 - - mysql-libs=8.0.31=hbc51c84_0 - - ncurses=6.3=h27087fc_1 - - nettle=3.8.1=hc379101_1 - - nspr=4.35=h27087fc_0 - - nss=3.82=he02c5a1_0 - - numpy=1.23.5=py39h3d75532_0 - - oauthlib=3.2.2=pyhd8ed1ab_0 - - opencv=4.6.0=py39hf3d152e_6 - - openh264=2.3.1=h27087fc_1 - - openjpeg=2.5.0=h7d73246_1 - - openssl=3.0.7=h0b41bf4_1 - - p11-kit=0.24.1=hc5aa10d_0 - - packaging=22.0=pyhd8ed1ab_0 - - pathspec=0.10.3=pyhd8ed1ab_0 - - pcre2=10.40=hc3806b6_0 - - pillow=9.2.0=py39hf3a2cdf_3 - - pip=22.3.1=pyhd8ed1ab_0 - - pixman=0.40.0=h36c2ea0_0 - - platformdirs=2.6.0=pyhd8ed1ab_0 - - pthread-stubs=0.4=h36c2ea0_1001 - - pulseaudio=16.1=h126f2b6_0 - - py-opencv=4.6.0=py39hcca971b_6 + - cython=3.0.0=py39h5eee18b_0 + - ffmpeg=4.3=hf484d3e_0 + - freetype=2.12.1=h4a9f257_0 + - giflib=5.2.1=h5eee18b_3 + - gmp=6.2.1=h295c915_3 + - gnutls=3.6.15=he1e5248_0 + - intel-openmp=2023.1.0=hdb19cb5_46305 + - jpeg=9e=h5eee18b_1 + - kiwisolver=1.4.4=py39h6a678d5_0 + - lame=3.100=h7b6447c_0 + - lcms2=2.12=h3be6417_0 + - ld_impl_linux-64=2.38=h1181459_1 + - lerc=3.0=h295c915_0 + - libdeflate=1.17=h5eee18b_0 + - libffi=3.4.4=h6a678d5_0 + - libgcc-ng=13.1.0=he5830b7_0 + - libgomp=13.1.0=he5830b7_0 + - libiconv=1.16=h7f8727e_2 + - libidn2=2.3.4=h5eee18b_0 + - libpng=1.6.39=h5eee18b_0 + - libstdcxx-ng=11.2.0=h1234567_1 + - libtasn1=4.19.0=h5eee18b_0 + - libtiff=4.5.0=h6a678d5_2 + - libunistring=0.9.10=h27cfd23_0 + - libuv=1.44.2=h5eee18b_0 + - libwebp=1.2.4=h11a3e52_1 + - libwebp-base=1.2.4=h5eee18b_1 + - lz4-c=1.9.4=h6a678d5_0 + - matplotlib-base=3.4.3=py39h2fa2bec_2 + - mkl=2023.1.0=h6d00ec8_46342 + - mkl-service=2.4.0=py39h5eee18b_1 + - mkl_fft=1.3.6=py39h417a72b_1 + - mkl_random=1.2.2=py39h417a72b_1 + - ncurses=6.4=h6a678d5_0 + - nettle=3.7.3=hbbd107a_1 + - numpy=1.25.0=py39h5f9d8c6_0 + - numpy-base=1.25.0=py39hb5e798b_0 + - openh264=2.1.1=h4ff587b_0 + - openssl=3.1.1=hd590300_1 + - pillow=9.4.0=py39h6a678d5_0 + - pip=23.2.1=py39h06a4308_0 - pycocotools=2.0.6=py39h2ae25f5_1 - - pycodestyle=2.10.0=pyhd8ed1ab_0 - - pycparser=2.21=pyhd8ed1ab_0 - - pyflakes=3.0.1=pyhd8ed1ab_0 - - pyjwt=2.6.0=pyhd8ed1ab_0 - - pyopenssl=22.1.0=pyhd8ed1ab_0 - - pyparsing=3.0.9=pyhd8ed1ab_0 - - pysocks=1.7.1=pyha2e5f31_6 - - python=3.9.15=hba424b6_0_cpython + - pyparsing=3.1.1=pyhd8ed1ab_0 + - python=3.9.17=h955ad1f_0 - python-dateutil=2.8.2=pyhd8ed1ab_0 - - python-wget=3.2=py_0 - - python_abi=3.9=3_cp39 - - pytorch=1.10.1=py3.9_cpu_0 + - python_abi=3.9=2_cp39 + - pytorch=1.10.0=py3.9_cpu_0 - pytorch-mutex=1.0=cpu - - pyyaml=6.0=py39hb9d737c_5 - - qt-main=5.15.6=hafeba50_4 + - pyyaml=6.0=py39h5eee18b_1 - readline=8.2=h5eee18b_0 - - requests=2.28.1=pyhd8ed1ab_1 - - requests-oauthlib=1.3.1=pyhd8ed1ab_0 - six=1.16.0=pyh6c4a22f_0 - - svt-av1=1.4.0=h27087fc_0 - - tk=8.6.12=h27826a3_0 - - tomli=2.0.1=pyhd8ed1ab_0 - - torchaudio=0.10.1=py39_cpu - - torchvision=0.11.2=py39_cpu - - tqdm=4.64.1=pyhd8ed1ab_0 - - typing-extensions=4.4.0=hd8ed1ab_0 - - typing_extensions=4.4.0=pyha770c72_0 - - tzdata=2022g=h191b570_0 - - unicodedata2=15.0.0=py39hb9d737c_0 - - urllib3=1.26.13=pyhd8ed1ab_0 - - wheel=0.38.4=pyhd8ed1ab_0 - - x264=1!164.3095=h166bdaf_2 - - x265=3.5=h924138e_3 - - xcb-util=0.4.0=h166bdaf_0 - - xcb-util-image=0.4.0=h166bdaf_0 - - xcb-util-keysyms=0.4.0=h166bdaf_0 - - xcb-util-renderutil=0.3.9=h166bdaf_0 - - xcb-util-wm=0.4.1=h166bdaf_0 - - xorg-fixesproto=5.0=h7f98852_1002 - - xorg-inputproto=2.3.2=h7f98852_1002 - - xorg-kbproto=1.0.7=h7f98852_1002 - - xorg-libice=1.0.10=h7f98852_0 - - xorg-libsm=1.2.3=hd9c2040_1000 - - xorg-libx11=1.7.2=h7f98852_0 - - xorg-libxau=1.0.9=h7f98852_0 - - xorg-libxdmcp=1.1.3=h7f98852_0 - - xorg-libxext=1.3.4=h7f98852_1 - - xorg-libxfixes=5.0.3=h7f98852_1004 - - xorg-libxi=1.7.10=h7f98852_0 - - xorg-libxrender=0.9.10=h7f98852_1003 - - xorg-renderproto=0.11.1=h7f98852_1002 - - xorg-xextproto=7.3.0=h7f98852_1002 - - xorg-xproto=7.0.31=h7f98852_1007 - - xz=5.2.8=h5eee18b_0 - - yaml=0.2.5=h7f98852_2 - - zlib=1.2.13=h166bdaf_4 - - zstd=1.5.2=h6239696_4 + - sqlite=3.41.2=h5eee18b_0 + - tbb=2021.8.0=hdb19cb5_0 + - tk=8.6.12=h1ccaba5_0 + - torchaudio=0.10.0=py39_cpu + - torchvision=0.11.0=py39_cpu + - tornado=6.3.2=py39hd1e30aa_0 + - tqdm=4.65.0=pyhd8ed1ab_1 + - typing_extensions=4.7.1=py39h06a4308_0 + - tzdata=2023c=h04d1e81_0 + - wheel=0.38.4=py39h06a4308_0 + - xz=5.4.2=h5eee18b_0 + - yaml=0.2.5=h7b6447c_0 + - zlib=1.2.13=h5eee18b_0 + - zstd=1.5.5=hc292b87_0 - pip: - - setuptools==59.5.0 + - attrs==23.1.0 + - boxsdk==3.8.1 + - cffi==1.15.1 + - charset-normalizer==3.2.0 + - cryptography==41.0.3 + - idna==3.4 + - opencv-python==4.8.0.74 + - pycparser==2.21 + - pyjwt==2.8.0 + - requests==2.31.0 + - requests-toolbelt==1.0.0 + - urllib3==1.26.16 + - wget==3.2 + - setuptools==59.5.0 diff --git a/config/parameters.yaml b/config/parameters.yaml index 862eb68..e4f4adc 100644 --- a/config/parameters.yaml +++ b/config/parameters.yaml @@ -1,6 +1,6 @@ # Dataset Size and Split Parameters dataset_params: - train_images: 20 + train_images: 25 val_images: 8 train_split: 0.8 @@ -14,13 +14,13 @@ shape: # The value num_categories is reserved to represent the “background” category, if applicable. categories: device: 1 - wire: 2 + single-wire: 2 background: 3 # Color Thresholding Values for Each Object Category color_threshold: device: 50 - wire: 30 + single-wire: 30 # Contur Minimum Area (in pixels) Threshold Value contour_threshold: 1000 @@ -28,7 +28,7 @@ contour_threshold: 1000 # Maximum Number of Instances Per Image for Each Object Category max_inst: device: 2 - wire: 4 + single-wire: 4 # Parameters for Scale Jittering scale_jittering: @@ -75,7 +75,7 @@ predict_dataset: False # Options: "train" and "val" dataset_verification: which_dataset: "val" - number_of_images: 2 + number_of_images: 10 dataset_prediction: number_of_images: 5 @@ -84,4 +84,4 @@ dataset_prediction: directory: root_dir: "." dataset_dir_name: "cocopen-dataset" - AZURE_STORAGE_CONNECTION_STRING: 'DefaultEndpointsProtocol=https;AccountName=uiucwiresdataset;AccountKey=VkJ1HT3LkDuiLTFK8yd+eAFLvhLKJNqLDIealTPY9Lv6Dp7VDFVWKIvhnNXqC+GCQYjh7NQVuH1r+ASt/tVk7g==;EndpointSuffix=core.windows.net' + BOX_CONFIG_FILE_PATH: './config/config.json' \ No newline at end of file diff --git a/config/train_environment.yaml b/config/train_environment.yaml index b04f483..e74cdfd 100644 --- a/config/train_environment.yaml +++ b/config/train_environment.yaml @@ -1,226 +1,107 @@ name: cocopen-train channels: - pytorch - - anaconda - conda-forge - defaults dependencies: - _libgcc_mutex=0.1=conda_forge - - _openmp_mutex=4.5=2_gnu - - alsa-lib=1.2.8=h166bdaf_0 - - aom=3.5.0=h27087fc_0 - - attr=2.5.1=h166bdaf_1 - - azure-core=1.26.1=pyhd8ed1ab_0 - - azure-storage-blob=12.14.1=pyhd8ed1ab_0 - - black=22.10.0=py39hf3d152e_2 + - _openmp_mutex=4.5=2_kmp_llvm - blas=1.0=mkl - - blinker=1.5=pyhd8ed1ab_0 - - brotli=1.0.9=h166bdaf_8 - - brotli-bin=1.0.9=h166bdaf_8 - - brotlipy=0.7.0=py39hb9d737c_1005 - - bzip2=1.0.8=h7f98852_4 - - c-ares=1.18.1=h7f98852_0 - - ca-certificates=2022.12.7=ha878542_0 - - cairo=1.16.0=ha61ee94_1014 - - certifi=2022.12.7=pyhd8ed1ab_0 - - cffi=1.15.1=py39he91dace_2 - - charset-normalizer=2.1.1=pyhd8ed1ab_0 - - click=8.1.3=unix_pyhd8ed1ab_2 - - colorama=0.4.6=pyhd8ed1ab_0 - - contourpy=1.0.6=py39hf939315_0 - - cryptography=38.0.4=py39h3ccb8fc_0 - - cudatoolkit=11.3.1=h9edb442_11 - - cycler=0.11.0=pyhd8ed1ab_0 - - cython=0.29.32=py39h5a03fae_1 - - dbus=1.13.18=hb2f20db_0 - - expat=2.5.0=h27087fc_0 - - ffmpeg=5.1.2=gpl_h13415ed_104 - - fftw=3.3.10=nompi_hf0379b8_106 - - flake8=6.0.0=pyhd8ed1ab_0 - - font-ttf-dejavu-sans-mono=2.37=hab24e00_0 - - font-ttf-inconsolata=3.000=h77eed37_0 - - font-ttf-source-code-pro=2.038=h77eed37_0 - - font-ttf-ubuntu=0.83=hab24e00_0 - - fontconfig=2.14.1=hc2a2eb6_0 - - fonts-conda-ecosystem=1=0 - - fonts-conda-forge=1=0 - - fonttools=4.38.0=py39hb9d737c_1 - - freeglut=3.2.2=h9c3ff4c_1 - - freetype=2.12.1=hca18f0e_1 - - gettext=0.21.1=h27087fc_0 - - glib=2.74.1=h6239696_1 - - glib-tools=2.74.1=h6239696_1 - - gmp=6.2.1=h58526e2_0 - - gnutls=3.7.8=hf3e180e_0 - - graphite2=1.3.14=h295c915_1 - - gst-plugins-base=1.21.2=h3e40eee_0 - - gstreamer=1.21.2=hd4edc92_0 - - gstreamer-orc=0.4.33=h166bdaf_0 - - harfbuzz=5.3.0=h418a68e_0 - - hdf5=1.12.2=nompi_h4df4325_100 - - icu=70.1=h27087fc_0 - - idna=3.4=pyhd8ed1ab_0 - - intel-openmp=2022.1.0=h9e868ea_3769 - - isodate=0.6.1=pyhd8ed1ab_0 - - jack=1.9.21=h583fa2b_2 - - jasper=2.0.33=ha77e612_0 - - jpeg=9e=h166bdaf_2 - - keyutils=1.6.1=h166bdaf_0 - - kiwisolver=1.4.4=py39hf939315_1 - - krb5=1.19.3=h08a2579_0 - - lame=3.100=h166bdaf_1003 - - lcms2=2.14=h6ed2654_0 - - ld_impl_linux-64=2.39=hcc3a1bd_1 - - lerc=4.0.0=h27087fc_0 - - libblas=3.9.0=16_linux64_mkl - - libbrotlicommon=1.0.9=h166bdaf_8 - - libbrotlidec=1.0.9=h166bdaf_8 - - libbrotlienc=1.0.9=h166bdaf_8 - - libcap=2.66=ha37c62d_0 - - libcblas=3.9.0=16_linux64_mkl - - libclang=15.0.6=default_h2e3cab8_0 - - libclang13=15.0.6=default_h3a83d3e_0 - - libcups=2.3.3=h3e49a29_2 - - libcurl=7.86.0=h2283fc2_1 - - libdb=6.2.32=h9c3ff4c_0 - - libdeflate=1.14=h166bdaf_0 - - libdrm=2.4.114=h166bdaf_0 - - libedit=3.1.20210910=h7f8727e_0 - - libev=4.33=h516909a_1 - - libevent=2.1.10=h28343ad_4 - - libffi=3.4.2=h7f98852_5 - - libflac=1.4.2=h27087fc_0 - - libgcc-ng=12.2.0=h65d4601_19 - - libgcrypt=1.10.1=h166bdaf_0 - - libgfortran-ng=12.2.0=h69a702a_19 - - libgfortran5=12.2.0=h337968e_19 - - libglib=2.74.1=h606061b_1 - - libglu=9.0.0=he1b5a44_1001 - - libgomp=12.2.0=h65d4601_19 - - libgpg-error=1.45=hc0c96e0_0 - - libiconv=1.17=h166bdaf_0 - - libidn2=2.3.4=h166bdaf_0 - - liblapack=3.9.0=16_linux64_mkl - - liblapacke=3.9.0=16_linux64_mkl - - libllvm15=15.0.6=h63197d8_0 - - libnghttp2=1.47.0=hff17c54_1 - - libnsl=2.0.0=h7f98852_0 - - libogg=1.3.5=h27cfd23_1 - - libopenblas=0.3.21=pthreads_h78a6416_3 - - libopencv=4.6.0=py39h9757d25_6 - - libopus=1.3.1=h7f98852_1 - - libpciaccess=0.17=h166bdaf_0 - - libpng=1.6.39=h753d276_0 - - libpq=15.1=h67c24c5_1 - - libprotobuf=3.21.11=h3eb15da_0 - - libsndfile=1.1.0=hcb278e6_1 - - libsqlite=3.40.0=h753d276_0 - - libssh2=1.10.0=hf14f497_3 - - libstdcxx-ng=12.2.0=h46fd767_19 - - libsystemd0=252=h2a991cd_0 - - libtasn1=4.19.0=h166bdaf_0 - - libtiff=4.4.0=h55922b4_4 - - libtool=2.4.6=h9c3ff4c_1008 - - libudev1=252=h166bdaf_0 - - libunistring=0.9.10=h7f98852_0 - - libuuid=2.32.1=h7f98852_1000 - - libuv=1.44.2=h166bdaf_0 - - libva=2.16.0=h166bdaf_0 - - libvorbis=1.3.7=h9c3ff4c_0 - - libvpx=1.11.0=h9c3ff4c_3 - - libwebp-base=1.2.4=h166bdaf_0 - - libxcb=1.13=h7f98852_1004 - - libxkbcommon=1.0.3=he3ba5ed_0 - - libxml2=2.10.3=h7463322_0 - - libzlib=1.2.13=h166bdaf_4 - - lz4-c=1.9.3=h9c3ff4c_1 - - matplotlib-base=3.6.2=py39hf9fd14e_0 - - mccabe=0.7.0=pyhd3eb1b0_0 - - mkl=2022.1.0=hc2b9512_224 - - mpg123=1.31.1=h27087fc_0 - - msrest=0.7.1=pyhd8ed1ab_0 - - munkres=1.1.4=pyh9f0ad1d_0 - - mypy_extensions=0.4.3=py39hf3d152e_6 - - mysql-common=8.0.31=h26416b9_0 - - mysql-libs=8.0.31=hbc51c84_0 - - ncurses=6.3=h27087fc_1 - - nettle=3.8.1=hc379101_1 - - nspr=4.35=h27087fc_0 - - nss=3.82=he02c5a1_0 - - numpy=1.23.5=py39h3d75532_0 - - oauthlib=3.2.2=pyhd8ed1ab_0 - - opencv=4.6.0=py39hf3d152e_6 - - openh264=2.3.1=h27087fc_1 - - openjpeg=2.5.0=h7d73246_1 - - openssl=3.0.7=h0b41bf4_1 - - p11-kit=0.24.1=hc5aa10d_0 - - packaging=22.0=pyhd8ed1ab_0 - - pathspec=0.10.3=pyhd8ed1ab_0 - - pcre2=10.40=hc3806b6_0 - - pillow=9.2.0=py39hf3a2cdf_3 - - pip=22.3.1=pyhd8ed1ab_0 - - pixman=0.40.0=h36c2ea0_0 - - platformdirs=2.6.0=pyhd8ed1ab_0 - - pthread-stubs=0.4=h36c2ea0_1001 - - pulseaudio=16.1=h126f2b6_0 - - py-opencv=4.6.0=py39hcca971b_6 + - brotli=1.0.9=h5eee18b_7 + - brotli-bin=1.0.9=h5eee18b_7 + - bzip2=1.0.8=h7b6447c_0 + - ca-certificates=2023.05.30=h06a4308_0 + - certifi=2023.7.22=py39h06a4308_0 + - colorama=0.4.6=py39h06a4308_0 + - contourpy=1.0.5=py39hdb19cb5_0 + - cudatoolkit=11.3.1=h9edb442_10 + - cycler=0.11.0=pyhd3eb1b0_0 + - cython=3.0.0=py39h5eee18b_0 + - ffmpeg=4.2.2=h20bf706_0 + - fonttools=4.25.0=pyhd3eb1b0_0 + - freetype=2.12.1=h4a9f257_0 + - giflib=5.2.1=h5eee18b_3 + - gmp=6.2.1=h295c915_3 + - gnutls=3.6.15=he1e5248_0 + - importlib_resources=5.2.0=pyhd3eb1b0_1 + - intel-openmp=2023.1.0=hdb19cb5_46305 + - jpeg=9e=h5eee18b_1 + - kiwisolver=1.4.4=py39h6a678d5_0 + - lame=3.100=h7b6447c_0 + - lcms2=2.12=h3be6417_0 + - ld_impl_linux-64=2.38=h1181459_1 + - lerc=3.0=h295c915_0 + - libbrotlicommon=1.0.9=h5eee18b_7 + - libbrotlidec=1.0.9=h5eee18b_7 + - libbrotlienc=1.0.9=h5eee18b_7 + - libdeflate=1.17=h5eee18b_0 + - libffi=3.4.4=h6a678d5_0 + - libgcc-ng=13.1.0=he5830b7_0 + - libidn2=2.3.4=h5eee18b_0 + - libopus=1.3.1=h7b6447c_0 + - libpng=1.6.39=h5eee18b_0 + - libstdcxx-ng=11.2.0=h1234567_1 + - libtasn1=4.19.0=h5eee18b_0 + - libtiff=4.5.0=h6a678d5_2 + - libunistring=0.9.10=h27cfd23_0 + - libuv=1.44.2=h5eee18b_0 + - libvpx=1.7.0=h439df22_0 + - libwebp=1.2.4=h11a3e52_1 + - libwebp-base=1.2.4=h5eee18b_1 + - llvm-openmp=14.0.6=h9e868ea_0 + - lz4-c=1.9.4=h6a678d5_0 + - matplotlib-base=3.7.1=py39h417a72b_1 + - mkl=2023.1.0=h6d00ec8_46342 + - mkl-service=2.4.0=py39h5eee18b_1 + - mkl_fft=1.3.6=py39h417a72b_1 + - mkl_random=1.2.2=py39h417a72b_1 + - munkres=1.1.4=py_0 + - ncurses=6.4=h6a678d5_0 + - nettle=3.7.3=hbbd107a_1 + - numpy=1.25.0=py39h5f9d8c6_0 + - numpy-base=1.25.0=py39hb5e798b_0 + - openh264=2.1.1=h4ff587b_0 + - openssl=3.0.9=h7f8727e_0 + - packaging=23.0=py39h06a4308_0 + - pillow=9.4.0=py39h6a678d5_0 + - pip=23.2.1=py39h06a4308_0 - pycocotools=2.0.6=py39h2ae25f5_1 - - pycodestyle=2.10.0=pyhd8ed1ab_0 - - pycparser=2.21=pyhd8ed1ab_0 - - pyflakes=3.0.1=pyhd8ed1ab_0 - - pyjwt=2.6.0=pyhd8ed1ab_0 - - pyopenssl=22.1.0=pyhd8ed1ab_0 - - pyparsing=3.0.9=pyhd8ed1ab_0 - - pysocks=1.7.1=pyha2e5f31_6 - - python=3.9.15=hba424b6_0_cpython - - python-dateutil=2.8.2=pyhd8ed1ab_0 - - python-wget=3.2=py_0 - - python_abi=3.9=3_cp39 + - pyparsing=3.0.9=py39h06a4308_0 + - python=3.9.17=h955ad1f_0 + - python-dateutil=2.8.2=pyhd3eb1b0_0 + - python_abi=3.9=2_cp39 - pytorch=1.10.0=py3.9_cuda11.3_cudnn8.2.0_0 - pytorch-mutex=1.0=cuda - - pyyaml=6.0=py39hb9d737c_5 - - qt-main=5.15.6=hafeba50_4 + - pyyaml=6.0=py39h5eee18b_1 - readline=8.2=h5eee18b_0 - - requests=2.28.1=pyhd8ed1ab_1 - - requests-oauthlib=1.3.1=pyhd8ed1ab_0 - - six=1.16.0=pyh6c4a22f_0 - - svt-av1=1.4.0=h27087fc_0 - - tk=8.6.12=h27826a3_0 - - tomli=2.0.1=pyhd8ed1ab_0 + - six=1.16.0=pyhd3eb1b0_1 + - sqlite=3.41.2=h5eee18b_0 + - tbb=2021.8.0=hdb19cb5_0 + - tk=8.6.12=h1ccaba5_0 - torchaudio=0.10.0=py39_cu113 - torchvision=0.11.0=py39_cu113 - - tqdm=4.64.1=pyhd8ed1ab_0 - - typing-extensions=4.4.0=hd8ed1ab_0 - - typing_extensions=4.4.0=pyha770c72_0 - - tzdata=2022g=h191b570_0 - - unicodedata2=15.0.0=py39hb9d737c_0 - - urllib3=1.26.13=pyhd8ed1ab_0 - - wheel=0.38.4=pyhd8ed1ab_0 - - x264=1!164.3095=h166bdaf_2 - - x265=3.5=h924138e_3 - - xcb-util=0.4.0=h166bdaf_0 - - xcb-util-image=0.4.0=h166bdaf_0 - - xcb-util-keysyms=0.4.0=h166bdaf_0 - - xcb-util-renderutil=0.3.9=h166bdaf_0 - - xcb-util-wm=0.4.1=h166bdaf_0 - - xorg-fixesproto=5.0=h7f98852_1002 - - xorg-inputproto=2.3.2=h7f98852_1002 - - xorg-kbproto=1.0.7=h7f98852_1002 - - xorg-libice=1.0.10=h7f98852_0 - - xorg-libsm=1.2.3=hd9c2040_1000 - - xorg-libx11=1.7.2=h7f98852_0 - - xorg-libxau=1.0.9=h7f98852_0 - - xorg-libxdmcp=1.1.3=h7f98852_0 - - xorg-libxext=1.3.4=h7f98852_1 - - xorg-libxfixes=5.0.3=h7f98852_1004 - - xorg-libxi=1.7.10=h7f98852_0 - - xorg-libxrender=0.9.10=h7f98852_1003 - - xorg-renderproto=0.11.1=h7f98852_1002 - - xorg-xextproto=7.3.0=h7f98852_1002 - - xorg-xproto=7.0.31=h7f98852_1007 - - xz=5.2.8=h5eee18b_0 - - yaml=0.2.5=h7f98852_2 - - zlib=1.2.13=h166bdaf_4 - - zstd=1.5.2=h6239696_4 + - tqdm=4.65.0=pyhd8ed1ab_1 + - typing_extensions=4.7.1=py39h06a4308_0 + - tzdata=2023c=h04d1e81_0 + - wheel=0.38.4=py39h06a4308_0 + - x264=1!157.20191217=h7b6447c_0 + - xz=5.4.2=h5eee18b_0 + - yaml=0.2.5=h7b6447c_0 + - zipp=3.11.0=py39h06a4308_0 + - zlib=1.2.13=h5eee18b_0 + - zstd=1.5.5=hc292b87_0 - pip: - - setuptools==59.5.0 + - attrs==23.1.0 + - boxsdk==3.8.1 + - cffi==1.15.1 + - charset-normalizer==3.2.0 + - cryptography==41.0.3 + - idna==3.4 + - opencv-python==4.8.0.74 + - pycparser==2.21 + - pyjwt==2.8.0 + - requests==2.31.0 + - requests-toolbelt==1.0.0 + - urllib3==1.26.16 + - wget==3.2 + - setuptools==59.5.0 diff --git a/docs/EXAMPLE_RUN.md b/docs/EXAMPLE_RUN.md index 384d85f..9f03728 100644 --- a/docs/EXAMPLE_RUN.md +++ b/docs/EXAMPLE_RUN.md @@ -6,30 +6,21 @@ For this example demo we will be using foreground (wire and device) and backgrou ## **1. Open COCOpen** -Navigate into the COCOpen repository. +Navigate into the COCOpen directory ```bash -# Navigate into the COCOpen directory -$ cd COCOCpen-OpenCV +cd COCOCpen-OpenCV ``` ## **2. Configure Data** -a. The provided `config/parameters.yaml` file already contains an Azure connection string that is ready to generate data using the UIUC wires dataset. - -```yaml -# Pointer to raw input imagery and directory structuring -user_defined: - root_dir: "." # ignore - dataset_directory_name: "cocopen-dataset" # ignore - AZURE_STORAGE_CONNECTION_STRING: 'DefaultEndpointsProtocol=https;AccountName=uiucwiresdataset;AccountKey=VkJ1HT3LkDuiLTFK8yd+eAFLvhLKJNqLDIealTPY9Lv6Dp7VDFVWKIvhnNXqC+GCQYjh7NQVuH1r+ASt/tVk7g==;EndpointSuffix=core.windows.net' # UIUC's Azure connection string -``` +The provided `config/config.json` file already contains the Box application settings that are ready to generate data using the UIUC wires dataset. To connect to your own Box application that stores your own dataset, follow [these instructions](http://opensource.box.com/box-python-sdk/). ## **3. Adjust Parameters** Open the `config/parameters.yaml` file. -Tweak parameters such as `dataset_dir_name` (the name of the generated dataset directory), `train_images` (the number of images in the generated training set), `threshold` (color thresholding values), and `max_instances` (the maximum number of objects of a particular category per image). We recommend keeping the [default](config/parameters.yaml) values provided for this example run. Below are some of the tunable parameters defining a new dataset: +Modify parameters such as the name of the generated dataset directory, `dataset_dir_name`, the number of images in the training data set, `train_images`, the threshold for color-based segmentation, `threshold`, and the maximum number of objects of a particular category per image, `max_instances`. We recommend keeping the [default](../config/parameters.yaml) values provided for this example run. Below are some of the tunable parameters defining a new dataset: ```yaml # Dataset Size and Split Parameters @@ -56,15 +47,14 @@ max_inst: ``` ## **4. Run COCOpen** -To execute COCOpen, run: - +To execute COCOpen, run ```bash -# Run COCOpen -$ ./run.sh +./run.sh ``` ## **5. Result** -You can now find the generated dataset in the `datasets` folder. Example annotations are provided in the image below. + +The generated dataset will appear in the `datasets` folder. Example annotations are provided in the image below.

This is an example COCOpen-produced synthetic image containing multiple objects of interest superimposed on a randomly selected background. It visualizes ground truth instance segmentation mask, object category, and bounding box labels.

diff --git a/docs/INSTALLATION.md b/docs/INSTALLATION.md index a975bc6..d460592 100644 --- a/docs/INSTALLATION.md +++ b/docs/INSTALLATION.md @@ -8,92 +8,94 @@ Installation and execution of COCOpen was verified with the below environment. - Operating System: Ubuntu 20.04.5 LTS - Kernel: Linux 5.15.0-56-generic - Architecture: x86-64 -- Python: 3.9.15 +- Python: 3.9.17 - Conda: 22.9.0 -All dependencies were also verified with every combination of [ubuntu-18.04, ubuntu-20.04, ubuntu-22.04] x [python-3.7, python-3.8, python-3.9, python-3.10] through Github continuous integration testing. +See the repository GitHub CI/CD workflow [file](https://github.com/RMDLO/COCOpen-OpenCV/blob/main/.github/workflows/env.yaml) for more information on system and python compatibility. For detailed versions of package dependencies, please see [`config/data_environment.yaml`](https://github.com/RMDLO/COCOpen-OpenCV/blob/main/config/data_environment.yaml). -## **Clone COCOpen-OpenCV Repository** +## **Clone Repository** + +Clone this repository with: -Clone this COCOpen-OpenCV in your desired location by running the following command in a terminal: ```bash -# Clone the repository -$ git clone https://github.com/RMDLO/COCOpen-OpenCV.git +git clone https://github.com/RMDLO/COCOpen-OpenCV.git ``` -## **Use Conda** +## **Demonstrate Data Generation** COCOpen-OpenCV uses an conda environment to manage versions of all dependencies. To get started with installing `conda` please follow [these instructions](https://conda.io/projects/conda/en/latest/user-guide/getting-started.html). For ease of creating a conda environment, COCOpen provides an `data_environment.yaml` file in the `config/` directory of this repository. The first line of the `data_environment.yaml` file defines the name of the new environment. This environment is used to generate a synthetic dataset using `src/cocopen.py`. To visualize the generated dataset, we include dependencies for the object detection library we use, [detectron2](https://github.com/facebookresearch/detectron2). The conda environment includes a cpu-only installation of PyTorch 1.10 on which detectron2 visualization depends. The detectron2 library cannot be installed with `conda` because it will not build properly with PyTorch. To use COCOpen to generate and visualize a dataset, please run the below commands to install dependencies. +Navigate into the COCOpen directory + ```bash -# Navigate into the COCOpen directory -$ cd COCOCpen-OpenCV +cd COCOCpen-OpenCV ``` + +Clone the conda environment + ```bash -# Clone the conda environment -$ conda env create -f config/data_environment.yaml +conda env create -f config/data_environment.yaml ``` + +Activate the conda environment + ```bash -# Activate the conda environment -$ conda activate cocopen-data +conda activate cocopen-data ``` + +Install the prebuilt detectron2 library ```bash -# Install the prebuilt detectron2 library -$ python -m pip install detectron2 -f https://dl.fbaipublicfiles.com/detectron2/wheels/cpu/torch1.10/index.html +python -m pip install detectron2 -f https://dl.fbaipublicfiles.com/detectron2/wheels/cpu/torch1.10/index.html ``` -Please also set the `demo_dataset` value in `config/parameters.yaml` to `True` to perform visualization. +Verify the `demo_dataset` value in `config/parameters.yaml` is set to `True` to perform visualization. -To train an object detection model, we provide a `train_environment.yaml` file which contains an installation of PyTorch 1.10 with CUDA 11.3. We also use the detectron2 library to train detection models. To set up a conda enviornment to use the `src/train.py` file to train and predict on a dataset, please run: +## **Train an Instance Segmentation Model** + +The `train_environment.yaml` requirements file contains all dependencies required for training a detectron2 object instance segmentation model. To set up this conda environment (which the `src/train.py` file requires), please run: + +Navigate into the COCOpen directory ```bash -# Navigate into the COCOpen directory -$ cd COCOpen-OpenCV -``` -```bash -# Clone the conda environment -$ conda env create -f config/train_environment.yaml +cd COCOpen-OpenCV ``` + +Clone the conda environment + ```bash -# Activate the conda environment -$ conda activate cocopen-train +conda env create -f config/train_environment.yaml ``` + +Activate the conda environment + ```bash -# Install the prebuilt detectron2 library -$ python -m pip install detectron2 -f https://dl.fbaipublicfiles.com/detectron2/wheels/cu113/torch1.10/index.html +conda activate cocopen-train ``` -Please also set the `train_dataset` value in `config/parameters.yaml` to `True` to train a model. The model training configuration can be adjusted with user-defined training parameters in the `src/train.py` script. After training a model, you can perform inference with the model on validation set images by setting the `predict_dataset` value in `config/parameters.yaml` to `True`. +Install the prebuilt detectron2 library -## **Create an Azure Storage Container** - -These instructions are only necessary if you are providing your own input image dataset. Access to the UIUC Wires dataset comprising wire, device, and background images is provided by default. +```bash +python -m pip install detectron2 -f https://dl.fbaipublicfiles.com/detectron2/wheels/cu113/torch1.10/index.html +``` -Follow [these instructions](https://github.com/RMDLO/COCOpen-OpenCV/blob/main/docs/README_AZURE.md) to create an Azure storage container to store input data. To connect to an Azure storage container, perform the steps below. +Please also set the `train_dataset` value in `config/parameters.yaml` to `True` to train a model. The model training configuration can be adjusted with user-defined training parameters in `src/train.py`. After training a model, perform inference with the model on validation set images by setting the `predict_dataset` value in `config/parameters.yaml` to `True`. -1. Copy `connection string` from Azure Storage Account. Click [here](https://learn.microsoft.com/en-us/azure/storage/common/storage-account-keys-manage?toc=%2Fazure%2Fstorage%2Fblobs%2Ftoc.json&bc=%2Fazure%2Fstorage%2Fblobs%2Fbreadcrumb%2Ftoc.json&tabs=azure-portal#view-account-access-keys) to learn how to access it. +## **Create a Dataset with Box Cloud Storage** -2. Paste the connection string in the `config/parameters.yaml` file: +These instructions are only necessary for using COCOpen-OpenCV With user-supplied image data. Access to the UIUC Wires dataset, comprising wire, device, and background images, is provided by default. -```yaml -# Pointer to raw input imagery and directory structuring -user_defined: - root_dir: "." # ignore - dataset_directory_name: "cocopen-dataset" # ignore - AZURE_STORAGE_CONNECTION_STRING: '' -``` +Follow the [instructions](https://github.com/box/box-python-sdk) provided by BoxDev to create a Box application to store input data. To connect to the Box application, modify the Box application settings in `config/config.json` by following these [instructions](https://developer.box.com/guides/authentication/jwt/jwt-setup/#generate-a-keypair-recommended). -## **Running COCOpen** +## **Run COCOpen** -Open the `config/parameters.yaml` file and modify parameters like `dataset_name` (the name of the generated dataset directory), `train_images` (the number of images in the generated training set), and `max_instances` (the maximum number of objects of a particular category per image). Run COCOpen by performing: +Run COCOpen with ```bash -# Run COCOpen -$ ./run.sh +./run.sh ``` The generated dataset saves to the `datasets` directory under the root directory of this repository. See [example run](https://github.com/RMDLO/COCOpen-OpenCV/blob/main/docs/EXAMPLE_RUN.md) to see a demonstration of generating a simple dataset of ethernet cables and ethernet devices with category, bounding box, and instance segmentation mask annotations in the COCO format. diff --git a/docs/LEARN_MORE.md b/docs/LEARN_MORE.md index b9e2b30..cedc013 100644 --- a/docs/LEARN_MORE.md +++ b/docs/LEARN_MORE.md @@ -21,12 +21,12 @@ COCOpen performs the following tasks to automatically generate labeled object in This workflow is shown in the figure below.

- +

## **Custom Data** -The UIUCWires dataset stored on Azure is provided to demonstrate COCOpen by default. The dataset includes images of single wire and single devices against a black background. It also includes a folder of background images which are applied to generate background noise in the dataset as a form of data augmentation. Each image type (wire, device, and background) is stored in its own Azure storage container labeled with the object's category. All single-object images were captured with an Intel RealSense d435 camera with 1920x1080 resolution. The table below shows the number of images by object category. +The UIUCWires dataset stored on Box is provided to demonstrate COCOpen by default. The dataset includes images of single wire and single devices against a black background. It also includes a folder of background images which are applied to generate background noise in the dataset as a form of data augmentation. Each image type (wire, device, and background) is stored in its own folder labeled with the object's category. All single-object images were captured with an Intel RealSense d435 camera with 1920x1080 resolution. The table below shows the number of images by object category.
@@ -38,7 +38,7 @@ The UIUCWires dataset stored on Azure is provided to demonstrate COCOpen by defa The color contrast between the objects in each image and the background allows for using color thresholding to automatically annotate the original images. A user who wishes to use COCOpen to perform copy-paste augmentation on their own dataset will need to ensure the scene images only contain a single object. The scene for the images fed into COCOpen must also minimize shadowing. In our experience, the scene object can generate a shadow onto itself and the camera apparatus can generate a shadow onto the scene. For best results, we recommend checking lighting conditions before collecting data. -After users generate their own dataset of single-object RGB images, the images should be uploaded to individual storage containers on Azure. The container should contain only folders of images, and the title of each container of images should correspond to the object category label (all lower-case). See our [Configure Azure Storage Container](https://github.com/RMDLO/COCOpen-OpenCV/blob/main/docs/README_AZURE.md) documentation for more details and to see the directory structure for our container. +After users generate their own dataset of single-object RGB images, the images should be uploaded to individual folders on Box. The container should contain only folders of images, and the title of each container of images should correspond to the object category label (all lower-case). ## **References** diff --git a/docs/images/COCOpen.png b/docs/images/COCOpen.png index 0afb581..d14fce7 100644 Binary files a/docs/images/COCOpen.png and b/docs/images/COCOpen.png differ diff --git a/src/cocopen.py b/src/cocopen.py index c35a81b..ffea055 100644 --- a/src/cocopen.py +++ b/src/cocopen.py @@ -13,13 +13,13 @@ import numpy as np import cv2 from pycocotools import mask as pycocomask -from azure.storage.blob import BlobServiceClient +from boxsdk import JWTAuth, Client class COCOpen: """ The COCOpen class provides all functions necessary for automatically - annotating and augmenting a dataset of images stored on Azure. + annotating and augmenting a dataset of images stored on Box. """ def __init__( @@ -74,25 +74,26 @@ def __init__( ] self.category_to_container_client = {} + self.category_to_box_folder = {} self.category_to_train_list = {} self.category_to_val_list = {} - def init_azure( + def init_box( self, ) -> None: """ - Initializing Azure connection for for accessing blob storage + Initialize Box connection for accessing image data """ - # Initializing connection with Azure storage account - conn_str = self.param["directory"]["AZURE_STORAGE_CONNECTION_STRING"] - blob_service_client = BlobServiceClient.from_connection_string( - conn_str=conn_str - ) - # Map category names to blob_service_client of that category + # Initialize connection with Box client + config_file_path = self.param["directory"]["BOX_CONFIG_FILE_PATH"] + self.box_client = Client(JWTAuth.from_settings_file(config_file_path)) + root_folder = self.box_client.folder("0") + # Map category names to box folder object of that category for category in self.categories: - self.category_to_container_client[ - category["name"] - ] = blob_service_client.get_container_client(category["name"]) + for item in root_folder.get_items(): + if item.name == category["name"] and item.type == "folder": + self.category_to_box_folder[category["name"]] = item + break def make_new_dirs(self) -> None: """ @@ -153,38 +154,36 @@ def object_semantics( def create_image_list(self) -> None: """ - Creates foreground image list from images on Azure and + Creates foreground image list from images on Box and splits the list into 'train' and 'val' sets """ # Map category names to list of object images of that category for category in self.categories: # Creating list of all foreground images of that category - azure_category_all_list = self.category_to_container_client[ + box_category_all_list = self.category_to_box_folder[ category["name"] - ].list_blobs() + ].get_items() # Splitting foreground images into 'train' and 'val' sets train_list = [] val_list = [] - for blob in azure_category_all_list: + for box_image in box_category_all_list: rand = random.random() if 0 <= rand < self.param["dataset_params"]["train_split"]: - train_list.append(blob.name) + train_list.append(box_image.id) else: - val_list.append(blob.name) + val_list.append(box_image.id) self.category_to_train_list[category["name"]] = train_list self.category_to_val_list[category["name"]] = val_list - def download_image_from_azure(self, img, category): + def download_image_from_box(self, img_id): """ - Downloads image from Azure blob storage + Downloads image from Box storage """ - # Get blob and read image data into memory cache - blob = self.category_to_container_client[category].get_blob_client(img) - img_data = blob.download_blob().readall() - # Convert image data to numpy array - img_array = np.asarray(bytearray(img_data), dtype=np.uint8) + # Get file and read image data into memory cache + file = self.box_client.file(img_id) + file_data = file.content() # Decode image - src = cv2.imdecode(img_array, cv2.IMREAD_COLOR) + src = cv2.imdecode(np.frombuffer(file_data, np.uint8), cv2.IMREAD_COLOR) return src @@ -212,7 +211,7 @@ def contour_filter(self, frame, contour_max_area=2075000): def generate_supercategories(self): """ Generate dictionary for super categories based on param .yaml file. - Super categories are used when an object category, like "wire", may + Super categories are used when an object category, like "single-wire", may contain subcategories, like "ethernet" or "power." """ for key in self.param["categories"]: @@ -223,12 +222,12 @@ def generate_supercategories(self): } self.categories.append(supercategory_dict) - def get_object_info(self, img, category): + def get_object_info(self, img_id, category): """ This function returns the image array and the mask array """ # Get mask - src = self.download_image_from_azure(img=img, category=category) + src = self.download_image_from_box(img_id=img_id) median = cv2.medianBlur(src, 9) # Blur image gray = cv2.cvtColor(median, cv2.COLOR_BGR2GRAY) # Convert to grayscale _, mask = cv2.threshold( @@ -483,7 +482,6 @@ def random_flip(self, total_num_instances, all_img_arr, binary_mask_arr): Random flips """ for m in range(0, total_num_instances): - horizontal = int(2 * random.random()) vertical = int(2 * random.random()) @@ -502,9 +500,9 @@ def add_random_background(self, image_list, mask_array_1): Add random background """ randbg = int(random.random() * len(image_list["background"])) - bg_img = image_list["background"][randbg] - # Download background image from azure - src = self.download_image_from_azure(img=bg_img, category="background") + bg_img_id = image_list["background"][randbg] + # Download background image from box + src = self.download_image_from_box(img_id=bg_img_id) bg_arr = src.astype("uint8") # Exception: background image dimensions!=image shape parameter @@ -547,7 +545,6 @@ def combine_operations( Perform combine operations """ for i in tqdm(range(num_images)): - # scale factor for this image scale = scale_range[0] + random.random() * (scale_range[1] - scale_range[0]) @@ -612,7 +609,6 @@ def combine_operations( # update coco info for mask1 in binary_mask_arr[randint]: - mask_array_1.append(mask1) msk1 = np.zeros((self.height, self.width, 3)).astype("uint8") diff --git a/src/run.py b/src/run.py index a438af7..a51df7d 100644 --- a/src/run.py +++ b/src/run.py @@ -26,7 +26,6 @@ def main(params): # Generate a new COCO-formatted dataset if parameters["generate_dataset"]: - # initialize cocopen object cocopen = COCOpen( param=params, @@ -35,8 +34,8 @@ def main(params): # Create categories dictionary from parameters cocopen.generate_supercategories() - # Initializing Azure connection - cocopen.init_azure() + # Initializing Box connection + cocopen.init_box() # Make new directories cocopen.make_new_dirs() diff --git a/src/train.py b/src/train.py index be57c34..cc1bbeb 100644 --- a/src/train.py +++ b/src/train.py @@ -225,7 +225,6 @@ def __init__( self, parameters: dict, ) -> None: - self.parameters = parameters # COCO Dataset Loading @@ -284,4 +283,4 @@ def predict(self): f"./train/opencv/{self.name}_{self.model}", os.path.basename(ann["file_name"]), ) - cv2.imwrite(save_directory, out.get_image()) \ No newline at end of file + cv2.imwrite(save_directory, out.get_image())