Search code examples
pythonshapelydimension

ValueError: The ordinate (last) dimension should be 2 or 3, got 4


I'm trying to generate a confusion matrix for my Faster-RCNN object detection model. But before try it on model, i decided to try it with simple arrays. But i'm getting an error, I don't know what supposed to be input like.

I'm getting an error like this while trying to generate a confusion matrix:

Traceback (most recent call last):
  File "c:\Users\lemon\Desktop\ap_py_2\py_deneme.py", line 9, in <module>
    print(evaluation(grounds,preds,0.5))
  File "c:\Users\lemon\Desktop\ap_py_2\confusion_matrix.py", line 30, in evaluation
    f1=shapely.geometry.Polygon(f1)
  File "C:\Users\lemon\miniconda3\envs\cnn-env-03\lib\site-packages\shapely\geometry\polygon.py", line 229, in __new__
    shell = LinearRing(shell)
  File "C:\Users\lemon\miniconda3\envs\cnn-env-03\lib\site-packages\shapely\geometry\polygon.py", line 103, in __new__
    geom = shapely.linearrings(coordinates)
  File "C:\Users\lemon\miniconda3\envs\cnn-env-03\lib\site-packages\shapely\decorators.py", line 77, in wrapped
    return func(*args, **kwargs)
  File "C:\Users\lemon\miniconda3\envs\cnn-env-03\lib\site-packages\shapely\creation.py", line 173, in linearrings
    return lib.linearrings(coords, out=out, **kwargs)
ValueError: The ordinate (last) dimension should be 2 or 3, got 4

test.py:

from confusion_matrix import evaluation
import torch
import numpy as np

pred = [[13,24,25,46], [13,24,25,46], [13,24,25,46]]
ground = [[13,24,25,46],[13,24,25,46],[13,24,25,46]]
preds = np.array(pred)
grounds = np.array(ground)
print(evaluation(grounds,preds,0.5))

confusion_matrix.py: (source)

#!/usr/bin/env python
# coding: utf-8

import numpy as np
from shapely.geometry import Polygon,Point
import matplotlib.pyplot as plt
import shapely
import cv2 as cv
import os
import gc


def evaluation(ground,pred,iou_value):
  """
  ground= array of ground-truth contours.
  preds = array of predicted contours.
  iou_value= iou treshold for TP and otherwise.
  """
  truth=np.squeeze(ground)
  preds=np.squeeze(pred)
  #we will use this function to check iou less than threshold
  def CheckLess(list1,val):
    return(all(x<=val for x in list1))

  # Using predicted output as the reference
  prob1=[]
  for i in range(len(preds)):
      f1=np.expand_dims(preds[i], axis=0)
      # define a Shapely polygone for prediction i
      f1=shapely.geometry.Polygon(f1)
      # determine the radius
      f1_radius=np.sqrt((f1.area)/np.pi)
      #buffer the polygon fromt the centroid
      f1_buffered=shapely.geometry.Point(f1.centroid).buffer(f1_radius*500)
      cont=[]
      for i in range(len(truth)):
        ff=shapely.geometry.Polygon(np.squeeze(truth[i]))
        if f1_buffered.contains(ff)== True:
          iou=(ff.intersection(f1).area)/(ff.union(f1).area)  
       
          cont.append((iou))

      prob1.append(cont)

  fp=0

  for t in prob1:
    if CheckLess(t,iou_value)==True:
      fp=fp+1
    
  prob2=[]
  #loop through each groun truth instance 
  for i in range(len(truth)):
      f1=truth[i]
      f1=shapely.geometry.Polygon(f1)
      #find radius
      f1_radius=np.sqrt((f1.area)/np.pi)
      #buffer the polygon from the centroid
      f1_buffered=shapely.geometry.Point(f1.centroid).buffer(f1_radius*500)
      cont=[]
      # merge up the ground truth instance against prediction
      # to determine the IoU
      for i in range(len(preds)):
        ff=shapely.geometry.Polygon(np.squeeze(preds[i]))
        if f1_buffered.contains(ff)== True:
          #calculate IoU
          iou=(ff.intersection(f1).area)/(ff.union(f1).area)
          cont.append((iou))
      # probability of a given prediction to be contained in a
      # ground truth instance
      prob2.append(cont)
  fn=0
  tp=0
  for t in prob2:
    if np.sum(t)==0:
      fn=fn+1
    elif CheckLess(t,iou_value)==False:
      tp=tp+1
  
  #lets add this section just to print the results
  print("TP:",tp,"\t FP:",fp,"\t FN:",fn,"\t GT:",truth.shape[0])
  precision=round(tp/(tp+fp),3) 
  recall=round(tp/(tp+fn),3)
  f1= round(2*((precision*recall)/(precision+recall)),3)
  print("Precall:",precision,"\t Recall:",recall, "\t F1 score:",f1)
  
  return tp,fp,fn,precision,recall,f1

Solution

  • You are using the wrong data structure in your test. Due to the source, your data size should be n×m×2, where n is the number of instances, m - the number of (x,y) pairs of the mask. You have n=3, m=4 and miss the second coordinate on the plane.

    It looks like you tried manually add a new dimension in front of a row, which means you are trying to make a Polygon with one point in a 4-dimantional space, but Polygon doesn't accept points from 4D space and raises an error. Set up the correct dummy data structure (add a third dimension of size 2 to the arrays grounds and preds).