diff --git a/docs/napari_naive_bayes_colors.md b/docs/napari_naive_bayes_colors.md index c5a5571..1c10939 100644 --- a/docs/napari_naive_bayes_colors.md +++ b/docs/napari_naive_bayes_colors.md @@ -9,7 +9,7 @@ to get data for naive bayes functions. Collect pixel training data in Napari, ra - **Parameters:** - img - RGB image to extract color information from - - maskdict - dictionary of masks, output of [`napari_points_mask`](docs/napari_points_mask.md) for example + - maskdict - dictionary of masks, output of [`napari_points_mask`](napari_points_mask.md) for example - filename - filename to save data, formatted to work with [Naive Bayes segmentation](https://plantcv.readthedocs.io/en/latest/tutorials/machine_learning_tutorial/) - **Context:** diff --git a/docs/napari_read_coor.md b/docs/napari_read_coor.md index 04e21cd..9bf1e9c 100644 --- a/docs/napari_read_coor.md +++ b/docs/napari_read_coor.md @@ -1,6 +1,6 @@ ## Read point data into Napari Format -Save Points Labeled in Napari to a File +Read points from a file or dictionary into Napari format **plantcv.napari_read_coor**(*coor, dataformat = 'yx'*) @@ -8,10 +8,11 @@ Save Points Labeled in Napari to a File - **Parameters:** - coor - dictionary object of coordinates, or a path to json datafile with dictionary of point coordinates - - dataformat - either 'yx' or 'xy', Napari takes data as y,x format. If data is 'xy' data is converted from x,y to y,x + - dataformat - either 'yx', 'xy', or 'sam', Napari takes data as y,x format. If data is 'xy' data is converted from x,y to y,x. + If data is 'sam' point data is formatted for input into ultralytics sam3 functions. If 'sam' format is selected the function does expect a dictionary with 'pos' and 'neg' points as labelled classes. - **Context:** - - Import previously labeled points, or points from other functions (e.g. [`pcvan.napari_read_coor`](napari_read_coor.md)) + - Import previously labeled points, or points from other functions (e.g. [`pcvan.napari_save_coor`](napari_save_coor.md)) - **Example use:** - Below @@ -27,4 +28,18 @@ data = pcvan.napari_read_coor(coor ='coor.json', dataformat = 'xy') ``` +- **Example use for training Segment Anything Model:** + - Below + +```python +from ultralytics import SAM + +model = SAM("sam3.pt") +results = model.predict(source="./Example_image.jpg", + points=data["points"], + labels=data["labels"]) +results[0].show() + +``` + **Source Code:** [Here](https://github.com/danforthcenter/plantcv-annotate/blob/main/plantcv/annotate/napari_read_coor.py) diff --git a/plantcv/annotate/napari_read_coor.py b/plantcv/annotate/napari_read_coor.py index e571bac..64c230e 100755 --- a/plantcv/annotate/napari_read_coor.py +++ b/plantcv/annotate/napari_read_coor.py @@ -4,22 +4,21 @@ def napari_read_coor(coor, dataformat='yx'): - """ - open img in napari and label classes - - Inputs: - coor = either a dictionary of data or a path to a json file - with dictionary of point coordinates - dataformat = either 'yx' or 'xy'. Output of points function is in - x,y format and Napari is in y,x format. - - Returns: - data = dictionary of data - - :param coor: dict or str - :param dataformat: str - :return data: dictionary of data in y,x format for napari - + """Open img in napari and label classes + + Parameters + ---------- + coor : dict or str + Either a dictionary or path to json file of points and label classes. + dataformat : str + Use 'xy' for points function outputs, 'yx' for Napari outputs, and 'sam' for + Segment Anything Model, which includes "pos" and "neg" labeled classes; + defaults to 'yx'. + + Returns + ---------- + dict + Dictionary of points data. """ if isinstance(coor, dict): data = coor @@ -34,4 +33,22 @@ def napari_read_coor(coor, dataformat='yx'): data1.update({key: data2}) data = data1 + if dataformat == 'sam': + pointslist = [] + pointslabel = [] + + for i in enumerate(data['pos']): + x, y = i[1] + pointslist.append([x, y]) + pointslabel.append(1) + + for i in enumerate(data['neg']): + x, y = i[1] + pointslist.append([x, y]) + pointslabel.append(0) + + data1['points'] = [pointslist] + data1['labels'] = [pointslabel] + data = data1 + return data diff --git a/tests/test_napari_read_coor.py b/tests/test_napari_read_coor.py index 55be5ac..5f50d95 100644 --- a/tests/test_napari_read_coor.py +++ b/tests/test_napari_read_coor.py @@ -4,7 +4,7 @@ def test_napari_read_coor_napari(test_data): """Test for PlantCV.Annotate""" # Read in test data - data = napari_read_coor(test_data.coor_data, 'yx') + data = napari_read_coor(test_data.coor_data, dataformat='yx') assert isinstance(data, dict) @@ -12,7 +12,7 @@ def test_napari_read_coor_napari(test_data): def test_napari_read_coor_other(test_data): """Test for PlantCV.Annotate""" # Read in test data - data = napari_read_coor(test_data.coor_data, 'xy') + data = napari_read_coor(test_data.coor_data, dataformat='xy') assert data['germinated'][0] == (10, 25) @@ -21,6 +21,15 @@ def test_napari_read_coor_flip(): """Test for PlantCV.Annotate""" # Read in test data coor = {"germinated": [[25, 10]]} - data = napari_read_coor(coor, 'xy') + data = napari_read_coor(coor, dataformat='xy') assert data['germinated'][0] == (10, 25) + + +def test_napari_read_coor_sam(test_data): + """Test for PlantCV.Annotate""" + # Read in test data + coor = {'pos': [(284, 451)], 'neg': [(206, 160)]} + data = napari_read_coor(coor, dataformat='sam') + + assert data['points'][0][0][0] == 451