diff --git a/README.md b/README.md new file mode 100644 index 0000000..4d862ce --- /dev/null +++ b/README.md @@ -0,0 +1,51 @@ +[MIT License](./LICENSE) + +# Colony Counter +A simple Utility to count and measure bright spots on dark images 😸 + +## Features +- Image transformation results are cached and incremental. +- Provides an ugly user interface with intuitive key binds. +- Batch process/export image analysis results. + +- Adjust colony recognition and filtering through a couple of simple sliders. + +![](./readme_img/Filter_Colony.gif) + + +- Remove false positives by clicking on them. + +![](./readme_img/Remove_Colony.gif) + +## Getting Started +- Install python (>=3.8 recommended... I made sure to explicitly use ordered dictionaries but just in case). +- Install dependencies in whichever way you prefer. +- Create the folders "in", "out" and "cache" (or run colonycounter.py). +- Adjust queue functions in source code to suit your needs (and read through [Caveats](#caveats)). +- Copy/Move your images into the "in" folder. +- Start the program by running the colonycounter.py file. + +## Key Binds +| Key | Function | +|-----------------|----------------------------------------------------------------------------------------| +| q, left arrow | load previous image | +| w, right arrow | load next image | +| a | apply changes (always do this before switching images, otherwise changes will be lost) | +| r | reset changes that have not yet been applied | +| l | load saved settings from disk | +| s | save currently applied settings to disk | +| left mouse btn | add colony to list of ignored colonies | +| right mouse btn | remove colonies in the vicinity from ignore list | +| c | clear list of ignored colonies | +| e | batch process and export all images | + +## Caveats +- The current processing queue expects 16bit gray scale images with the file extension .tif (tagged image file). +- watershed function does not work on 16 bit images... so there are some hard coded values to bring measurements back to 16bit brightness values + - this means a loss of resolution +- To get hour and culture type values the following folder structure is expected: + - "$DIRIN/OPTIONAL\_FOLDERS/$HOUR/$CULTURETYPE/image.tif" + - $HOUR = integer followed by the letter h + - $CULTURETYPE = whatever string identifies your culture type +- Code documentation is currently lacking +- Not all types are properly annotated diff --git a/colonycounter.py b/colonycounter.py index 6303ca1..c9e5380 100644 --- a/colonycounter.py +++ b/colonycounter.py @@ -122,7 +122,6 @@ def main(): [f.opqueue.__init__([normalize, to8bit, rollingball, wat]) for f in files] [f.apply(dslice(f.opqueue,None,-1)) for f in files] - # [(f.apply(f.opqueue), f.save(True, f.opqueue)) for f in files] window.init(files) window.reset() return True diff --git a/fileutils.py b/fileutils.py index c88afad..e76aff3 100644 --- a/fileutils.py +++ b/fileutils.py @@ -53,7 +53,7 @@ class FILE: self.meta = pd.DataFrame(None if self.data[1]["data"][1:] == [] else self.data[1]["data"][1:], columns=self.data[1]["data"][0]) self.meta.insert(loc=0, column="Label", value="".join([self.fname, self.fext])) spath = self.path.split(path.sep) - if len(spath) > 2 and spath[-1] in ["BFP", "YFP"] and spath[-2][:-1].isdigit(): + if len(spath) > 2 and spath[-2][:-1].isdigit(): hour, culture = self.path.split(path.sep)[-2:] hour = int(hour[:-1]) else: @@ -82,11 +82,7 @@ class FILE: if self.outlines is not None: imwrite(path.join(DIROUT, self.path, f"{self.fname}.outlines.jpg"), self.outlines) if self.meta is not None: - print(path.join(DIROUT, self.path, f"{self.fname}.csv")) self.meta.to_csv(path.join(DIROUT, self.path, f"{self.fname}.csv"), index=False) - # [l.insert(1, self.getName(False, {})) for l in self.meta["data"][1:]] - # with open(path.join(DIROUT, self.path, f"{self.fname}.csv"), "w") as f: - # [f.write(",".join([str(e) for e in l]) + "\n") for l in self.meta["data"]] else: if not path.exists(path.join(DIRCACHE, self.path)): makedirs(path.join(DIRCACHE, self.path)) diff --git a/readme_img/Filter_Colony.gif b/readme_img/Filter_Colony.gif new file mode 100644 index 0000000..be2c7ab Binary files /dev/null and b/readme_img/Filter_Colony.gif differ diff --git a/readme_img/Remove_Colony.gif b/readme_img/Remove_Colony.gif new file mode 100644 index 0000000..1f992c6 Binary files /dev/null and b/readme_img/Remove_Colony.gif differ diff --git a/requirements.txt b/requirements.txt index fc993df..f496273 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ numpy opencv-python == 4.3.0 pythreshold -scikit-image +scikit-image >= 0.18.1 scipy