lilferrit commited on
Commit
ce20c03
1 Parent(s): d6201db

create usage guide

Browse files
Dockerfile CHANGED
@@ -1,6 +1,3 @@
1
- # read the doc: https://huggingface.co/docs/hub/spaces-sdks-docker
2
- # you will also find guides on how best to write your Dockerfile
3
-
4
  FROM python:3.10
5
 
6
  WORKDIR /code
 
 
 
 
1
  FROM python:3.10
2
 
3
  WORKDIR /code
MANIFEST.in CHANGED
@@ -1,2 +1,4 @@
1
- include eggcount/assets/*.jpg
2
- include eggcount/assets/*.png
 
 
 
1
+ include larvaecount/assets/*.jpg
2
+ include larvaecount/assets/*.png
3
+ include larvaecount/assets/*.css
4
+ include larvaecount/docs/*.md
larvaecount/assets/wiki_style.css ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ .wiki h2, .wiki h3, .wiki h4, .wiki h5, .wiki h6, .wiki p, .wiki li {
2
+ text-align: left;
3
+ }
larvaecount/docs/user_guide.md ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Larvae Counter User Guide
2
+
3
+ Welcome! This is a web-app that is equipped with a variety of tools to automate the counting
4
+ of mosquito larvae and pupae (although mostly pupae at this stage) from images. Currently, this
5
+ larvae counting tool has three automatic pupae counting tools based on "old-school" computer
6
+ vision techniques. However, a deep-learning method based off of the `YoloV8` architecture
7
+ is currently in development. Hypothetically, this deep learning method should be much less
8
+ susceptible to noise and allow the simultaneous counting of larvae and pupae, and maybe even
9
+ other stages of the mosquito life cycle. See below for a quick getting started guide.
10
+
11
+ ## Workflow
12
+
13
+ Below is the general workflow used to count mosquito larvae present in an image.
14
+
15
+ ### Step 1: Upload an Image
16
+
17
+ The first step is to upload an image containing pupae to be counted. This is done by either
18
+ clicking on or dragging an image file to the camera icon on the page. If this app is being
19
+ used on a smartphone an image can also be taken directly from the smartphone's camera by
20
+ tapping on the camera icon. After uploading an image, you can begin tunning parameters.
21
+
22
+ ### Step 2: Parameter Tuning
23
+
24
+ The next step is select your counting method and begin tuning the counting parameters. The
25
+ counting method can be selected in the drop-down list below the image upload box. The
26
+ `Gradient CC w/ filter` is recommended as the default counting algorithm. The parameters
27
+ for the selected counting method can be found in the box below the counting method drop-down
28
+ list.
29
+
30
+ It is recommend to click the `count` button with the default parameters to get a general
31
+ idea of how the parameters need to be changed in order to get better results. After changing
32
+ the parameters, click the `count` button again to re-run the selected algorithm with a new
33
+ set of parameters.
34
+
35
+ In general, parameters should be tuned from top down - meaning that the first parameter from the
36
+ top should be tuned to get satisfactory results, then the second parameter, and so on. The
37
+ images provided in the `Visualization` section of the results box (below the parameters box)
38
+ should be used to tune the parameters. More details will be given on each counting method and
39
+ its parameters below.
40
+
41
+ ### Step 3: Check Results
42
+
43
+ After the parameters have been tuned, the final results are available in the results box - which
44
+ is situated just below the counting parameters box.
45
+
46
+ ## Counting Algorithms
47
+
48
+ The larvae-count tool currently has three counting algorithms available, `Gradient CC w/ Filter`,
49
+ `Gradient CC`, and `Countour`.
50
+
51
+ ### Gradient CC w/ filter
52
+
53
+ `Gradient CC w/ Filter` (short for Gradient Connected Components with Elliptical Filter) counts
54
+ the pupae present in an image utilizing clusters. The algorithm first creates a gray scale image
55
+ from the provided image and applies a simple threshold in order to find pixels that are in a region
56
+ containing pupae. A filter is then applied to filter out any pixels flagged as pupae that aren't part
57
+ of a roughly elliptical pixel region. The algorithm than iterates over each overlapping cluster of
58
+ pupae (hence the connected components) and calculated the number of pupae in each cluster by
59
+ the area of the cluster in pixels.
60
+
61
+ #### Parameters
62
+
63
+ - `Color Threshold`: Cutoff below which a pixel in the gray-scale image will be considered to be
64
+ in a region containing pupae. The allowed values range from (0-255).
65
+ - `Average Area`: Average area (in pixels) of one pupae.
66
+ - `Max Pupae Per Cluster (Optional)`: Maximum number of pupae per cluster, used to filter out any
67
+ large dark blobs in the image.
68
+ - `Filter Kernel Width (Pixels)`: Width (in pixels) of the elliptical filter.
69
+ - `Filter Kernel Height (Pixels)`: Height (in pixels) of the elliptical filter.
70
+
71
+ ### Gradient CC
72
+
73
+ Same as `Gradient CC w/ Filter` but without the elliptical filter.
74
+
75
+ #### Parameters
76
+
77
+ - `Color Threshold`: Cutoff below which a pixel in the gray-scale image will be considered to be
78
+ in a region containing pupae. The allowed values range from (0-255).
79
+ - `Average Area`: Average area (in pixels) of one pupae.
80
+ - `Max Pupae Per Cluster (Optional)`: Maximum number of pupae per cluster, used to filter out any
81
+ large dark blobs in the image.
82
+
83
+ ### Gradient Contour w/ Filter
84
+
85
+ Similar to `Gradient CC w/ Filter`, but instead of iterating over every blob of "pupae pixels"
86
+ it iterates over regions contained within (an) elliptical contour(s).
87
+
88
+ #### Parameters
89
+
90
+ - `Color Threshold`: Cutoff below which a pixel in the gray-scale image will be considered to be
91
+ in a region containing pupae. The allowed values range from (0-255).
92
+ - `Average Area`: Average area (in pixels) of one pupae.
93
+ - `Max Pupae Per Cluster (Optional)`: Maximum number of pupae per cluster, used to filter out any
94
+ large dark blobs in the image.
95
+ - `Filter Kernel Width (Pixels)`: Width (in pixels) of the elliptical filter.
96
+ - `Filter Kernel Height (Pixels)`: Height (in pixels) of the elliptical filter.
larvaecount/gradient.py CHANGED
@@ -65,6 +65,7 @@ def component_filter_thresh(
65
  "Num-Eggs": num_eggs
66
  },
67
  "vis": {
 
68
  "Egg-Mask": bin_mask.astype(np.uint8),
69
  "Ellipse-Filter": close.astype(np.uint8),
70
  "Visualization": visualization_img.astype(np.uint8)
@@ -131,6 +132,7 @@ def component_thesh(
131
  "Num-Eggs": num_eggs
132
  },
133
  "vis": {
 
134
  "Egg-Mask": bin_mask.astype(np.uint8),
135
  "Visualization": visualization_img.astype(np.uint8)
136
  }
@@ -183,6 +185,7 @@ def contour_thresh(
183
  "Num-Eggs": num
184
  },
185
  "vis": {
 
186
  "Egg-Mask": bin_mask.astype(np.uint8),
187
  "Ellipse-Filter": close.astype(np.uint8),
188
  "Visualization": visualization_img.astype(np.uint8)
 
65
  "Num-Eggs": num_eggs
66
  },
67
  "vis": {
68
+ "Gray-Scale": img_gray.astype(np.uint8),
69
  "Egg-Mask": bin_mask.astype(np.uint8),
70
  "Ellipse-Filter": close.astype(np.uint8),
71
  "Visualization": visualization_img.astype(np.uint8)
 
132
  "Num-Eggs": num_eggs
133
  },
134
  "vis": {
135
+ "Gray-Scale": img_gray.astype(np.uint8),
136
  "Egg-Mask": bin_mask.astype(np.uint8),
137
  "Visualization": visualization_img.astype(np.uint8)
138
  }
 
185
  "Num-Eggs": num
186
  },
187
  "vis": {
188
+ "Gray-Scale": img_gray.astype(np.uint8),
189
  "Egg-Mask": bin_mask.astype(np.uint8),
190
  "Ellipse-Filter": close.astype(np.uint8),
191
  "Visualization": visualization_img.astype(np.uint8)
larvaecount/pages/guide.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from dash import html, dcc, callback, Input, Output, State
2
+ from larvaecount.ui.ui_utils import read_md_file
3
+
4
+ import dash
5
+ import dash_bootstrap_components as dbc
6
+ import os
7
+
8
+ dash.register_page(__name__, path = "/guide")
9
+
10
+ USER_GUIDE_PATH = os.path.abspath(
11
+ os.path.join(
12
+ os.path.dirname(__file__),
13
+ os.pardir,
14
+ "docs",
15
+ "user_guide.md"
16
+ )
17
+ )
18
+
19
+ layout = dbc.Container(
20
+ children = dcc.Markdown(
21
+ children = read_md_file(USER_GUIDE_PATH),
22
+ className = "wiki"
23
+ ),
24
+ class_name = "text-center mt-3"
25
+ )
26
+
larvaecount/pages/home.py CHANGED
@@ -31,11 +31,11 @@ UPLOAD_HEIGHT = "25vh"
31
 
32
  COUNT_FUNCS = {
33
  "Gradient CC": get_cc_ui,
34
- "Gradient CC w/ filter": get_cc_filter_ui,
35
- "Contour": get_contour_ui
36
  }
37
 
38
- DEFAULT_STRATEGY = "Gradient CC"
39
 
40
  def get_initial_upload_container() -> dbc.Container:
41
  return dcc.Upload(
@@ -64,7 +64,10 @@ def get_new_upload_container(
64
  image_data = BytesIO(decoded_bytes)
65
  pil_img = Image.open(image_data)
66
  img = np.array(pil_img)
67
- image_fig = px.imshow(img)
 
 
 
68
 
69
  return dbc.Container(
70
  children = [
@@ -72,7 +75,9 @@ def get_new_upload_container(
72
  children = file_name,
73
  className = "p-2 text-start",
74
  ),
75
- dcc.Graph(figure = image_fig),
 
 
76
  dbc.Container(
77
  children = dcc.Upload(
78
  children = dbc.Button(
 
31
 
32
  COUNT_FUNCS = {
33
  "Gradient CC": get_cc_ui,
34
+ "Gradient CC w/ Filter": get_cc_filter_ui,
35
+ "Gradient Contour w/ Filter": get_contour_ui
36
  }
37
 
38
+ DEFAULT_STRATEGY = "Gradient CC w/ Filter"
39
 
40
  def get_initial_upload_container() -> dbc.Container:
41
  return dcc.Upload(
 
64
  image_data = BytesIO(decoded_bytes)
65
  pil_img = Image.open(image_data)
66
  img = np.array(pil_img)
67
+ image_fig = px.imshow(
68
+ img,
69
+ height = 750,
70
+ )
71
 
72
  return dbc.Container(
73
  children = [
 
75
  children = file_name,
76
  className = "p-2 text-start",
77
  ),
78
+ dcc.Graph(
79
+ figure = image_fig,
80
+ ),
81
  dbc.Container(
82
  children = dcc.Upload(
83
  children = dbc.Button(
larvaecount/ui/ui_utils.py CHANGED
@@ -1,5 +1,6 @@
1
  from dash import html, dcc
2
  from typing import Dict
 
3
 
4
  import plotly.express as px
5
  import numpy as np
@@ -33,13 +34,6 @@ def get_navbar() -> dbc.Nav:
33
  href = "/guide",
34
  class_name = "text-light"
35
  )
36
- ),
37
- dbc.NavItem(
38
- children = dbc.NavLink(
39
- children = "About",
40
- href = "/about",
41
- class_name = "text-light"
42
- )
43
  )
44
  ],
45
  className = "bg-dark d-flex flex-row justify-content-start align-items-center",
@@ -247,7 +241,10 @@ def get_results_container(result: Dict) -> dbc.Container:
247
 
248
  for vis_name, vis_pic in result["vis"].items():
249
  children.append(html.H4(vis_name.replace("-", " ")))
250
- image_fig = px.imshow(vis_pic)
 
 
 
251
  children.append(
252
  dcc.Graph(
253
  figure = image_fig,
@@ -259,3 +256,7 @@ def get_results_container(result: Dict) -> dbc.Container:
259
  children = children,
260
  className = "p-3 m-0 border border-dark d-flex flex-column justify-content-center align-items-center"
261
  )
 
 
 
 
 
1
  from dash import html, dcc
2
  from typing import Dict
3
+ from os import PathLike
4
 
5
  import plotly.express as px
6
  import numpy as np
 
34
  href = "/guide",
35
  class_name = "text-light"
36
  )
 
 
 
 
 
 
 
37
  )
38
  ],
39
  className = "bg-dark d-flex flex-row justify-content-start align-items-center",
 
241
 
242
  for vis_name, vis_pic in result["vis"].items():
243
  children.append(html.H4(vis_name.replace("-", " ")))
244
+ image_fig = px.imshow(
245
+ vis_pic,
246
+ height = 750
247
+ )
248
  children.append(
249
  dcc.Graph(
250
  figure = image_fig,
 
256
  children = children,
257
  className = "p-3 m-0 border border-dark d-flex flex-column justify-content-center align-items-center"
258
  )
259
+
260
+ def read_md_file(md_file_path: PathLike) -> str:
261
+ with open(md_file_path, "r") as file:
262
+ return file.read()
setup.py CHANGED
@@ -4,5 +4,12 @@ setup(
4
  name = "larvaecount",
5
  version = "0.1",
6
  packages = find_packages(),
7
- package_data={"larvaecount": ["assets/*.jpg", "assets/*.png"]}
 
 
 
 
 
 
 
8
  )
 
4
  name = "larvaecount",
5
  version = "0.1",
6
  packages = find_packages(),
7
+ package_data = {
8
+ "larvaecount": [
9
+ "assets/*.jpg",
10
+ "assets/*.png",
11
+ "assets/*.css",
12
+ "docs/*.md"
13
+ ]
14
+ }
15
  )