Skip to content

Color card detection polygon extending outside of ROI #1950

Description

@joshqsumner

Describe the bug
When using pcv.transform.detect_color_card the roi argument is used to restrict where chips are found which I think implies that it restricts where the warped image will pull from, but that isn't always true.

  • Color card detection happens in one of two helpers, each of which is only called inside of _rect_filter, which forces them to only use the section of the image inside of the ROI. It would seem like this means everything in those functions respects the ROI but it does not force the polygon to only exist in the ROI.
    • chip detection (_find_color_chip_like_objects) happens in the ROI exclusively, only normal problems there.
    • A bounding rectangle is fit to those chips and rotated to "robust pos=3", still only the section of the image in the ROI.
    • cv2.approxPolyN is used to fit a polygon to the corners. This does not have to respect the ROI since the polygon does not know the size of the image, it just takes some points and fits a polygon that can extend anywhere. If the shape is approximately a rectangle then all good, but if it is not then this can get very far off from what we'd expect.
    • I have a few ideas but I don't like any of them much:
      • We could do something like the long answer here and check if absolute value of any angle - 90 is greater than 5 or 10 then warn if it is. I don't think this would be all that helpful actually.
      • What I'd like is to coerce the shape to stay inside the rectangle so we could say that any corner outside of the ROI gets smashed onto the edge of the ROI. That would make the ROI extra useful for really hard detection problems where if we think no chips are going to be detected we could put the ROI just inside the border of the chips (assuming they are oriented about correctly with the camera and that I'm thinking about this correctly). It would probably be reasonable to find half of the angle of that vertex that is off of the image, make a vector in that direction pointed back at the image, then take the new corner to be where that intersects with the edge of the image.

To Reproduce
Steps to reproduce the behavior (including sample data and code really help):

  1. Starting with very bad image call detect_color_card with an ROI
  2. See error
Image
# Note I am on a branch off of v5, no relevant edits to transform so v5 should demonstrate this well.
from plantcv import plantcv as pcv
img, path, filename = pcv.readimage(filename="mybadimage.jpg")
roi = pcv.roi.rectangle(img, 1175, 1950, 850, 600)
cc_mat = pcv.transform.detect_color_card(img, color_chip_size="passport")
Image

What isn't shown in the debug image is that the polygon converges to a "spike" off screen (since it is constrained to be 4 sided) you can imaging what it looks like.

Expected behavior
Ideally I'd like to force cv2.approxPolyN to only allow a certain range of angles/to take the 4 sided polygon and squash it into frame.

Local environment (please complete the following information):

  • OS: [Ubuntu]
  • Environment [conda]
  • PlantCV Version [e.g. 5.0.0]

Additional context
Add any other context about the problem here.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions