p2irc / deepplantphenomics

Deep learning for plant phenotyping.
GNU General Public License v2.0
135 stars 46 forks source link

Problem Type Refactoring and Object Counting Models #34

Closed donovanlavoie closed 5 years ago

donovanlavoie commented 5 years ago

First, this performs a major refactoring of DPP. DPPModel now serves as an abstract super class of common and default functionality while the different problem types, as represented by the ProblemType enum, are now implemented as sub classes of DPPModel.

This refactoring requires a change to the interface for creating models. Instead of creating a DPP model,

import deepplantpheonmics as dpp
model = dpp.DPPModel()
model.set_problem_type('regression')
...

... models are now created as follows:

import deepplantphenomics as dpp
model = dpp.RegressionModel()
...

The interface for existing settings functions remains mostly the same. set_problem_type was removed and some problem specific methods (like set_yolo_parameters) were moved to their respective problem sub classes.

Loader methods also kept their interfaces, but around half of them were moved into problem sub classes since the expected data sets for those functions was generally specific to those problems (especially for object detection).

Several common functions, like begin_training and parse_dataset, were refactored into parts so that DPPModel can contain the common structure (if any exists) and problem sub classes can override the specific parts that matter to them. An example would be semantic segmentation needing to override the image and label input portions of parse_dataset.

Some other common functions, like assemble_graph, add_output_layer, and forward_pass_with_file_inputs, were distinct enough between problems (barring some common pieces of assemble_graph) that they are abstract methods which each problem subclass must implement.

Second, two new problem types were added with different approaches to object counting.

The HeatmapObjectCountingModel is meant for counting objects through semantic segmentation. The inputs and outputs, however, are grayscale heatmaps with 2D gaussian distributions at the locations of object labels. It can load in data through a CSV file with x,y,x,y,... points as labels for each image, which are internally converted into a ground truth heatmap, or premade heatmaps can be loaded in a similar manner to segmentation masks.

The ConutCeptionModel also counts objects but by using a specific pre-defined model that performs redundant counting over heatmaps with square distributions at object locations. Its data, unlike other models, is loaded using a pickle file; the pickle file stores a list of ndarray tuples for the image data and its ground truth heatmap.

Count-ception expects batch-norm layers to come between convolution layers and activation layers and uses a new type of layer with 2 convolution filters in parallel. The paralConvBlock was added to facilitate this and the interface for the convLayer was extended to include the option to add batch-norm layers in the required spot.

The examples and tests have all been updated for the new model creation interface and additions have been made for the new problem types. All of the tests and examples should run fine.

jubbens commented 5 years ago

Congrats on getting the refactor done guys!

One thing which might be confusing is the presence of two different problem types for object counting, only one of which is documented in the object counting tutorial - can we expand the object counting tutorial with another section on counting using heatmap and some discussion of the differences?

@JianSu-Usask another thing which stands out to me in terms of usability is the new tool which is called tools.object_count_countception. I assume this is the flower counting tool? We should rename it and add its description to the Tools.md doc. Also, I don't have a network_state file for this tool. Where are the network weights?