title: python cv2 incorrectly detecting square shape in multiple images
body: <p>I've run into a problem detecting a square with opencv. </p>
  
  <ol>
  <li>Here is the reference image where I find the shape to match against used in cv2.matchShapes</li>
  </ol>
  
  <p><a href="https://i.stack.imgur.com/IwtdX.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/IwtdX.png" alt="reference image with just square"></a></p>
  
  <ol start="2">
  <li>Here are two input images used to compare against the reference image:</li>
  </ol>
  
  <p>first image:</p>
  
  <p><a href="https://i.stack.imgur.com/ecMLy.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/ecMLy.png" alt="reference image with same square with a five inside of it"></a></p>
  
  <p>second image:</p>
  
  <p><a href="https://i.stack.imgur.com/QOIVR.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/QOIVR.png" alt="reference image with same square with a five inside of it and assorted symbols and letters"></a></p>
  
  <ol start="3">
  <li><p>Here is the code I used (sorry for poor format):</p>
  
  <pre><code>#!/usr/bin/env python
  # coding: utf-8
  
  import numpy as np
  import cv2
  import argparse
  import math
  
  ap = argparse.ArgumentParser()
  ap.add_argument("-i", "--image", required=True, help="path to input image")
  args = vars(ap.parse_args())
  
  img = cv2.imread(args["image"])
  # img = cv2.bitwise_not(img,img)
  # gray = cv2.imread(args["image"],0)
  gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  
  # gray = cv2.GaussianBlur(gray, (5, 5), 0)
  cv2.imshow('gray', gray)
  cv2.waitKey(0)
  
  ret, thresh = cv2.threshold(gray, 230, 255, 1)
  cv2.imshow('thresh', thresh)
  # cv2.imwrite('./wni230.png',thresh)
  cv2.waitKey(0)
  
  square_cnts = []
  
  ##################################################
  shape = cv2.imread('./shape1.png')
  shape_gray = cv2.cvtColor(shape, cv2.COLOR_BGR2GRAY)
  ret, shape_thresh = cv2.threshold(shape_gray, 0, 255, 0)
  tmpimage, contours, h = cv2.findContours(shape_thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
  shape_cnt0 = contours[0]
  shape_approx = []
  for i in contours:
      approx = cv2.approxPolyDP(i, 0.01*cv2.arcLength(i, True), True)
      # print len(approx)
      if len(approx) == 4:
          shape_approx.append(len(approx))
  ##################################################
  # tmpimage,contours,h = cv2.findContours(thresh,1,2)
  # cv2.RETR_TREE
  tmpimage, contours, h = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
  cnt0 = contours[0]
  # from skimage import measure
  # contours = measure.find_contours(thresh, 0.8)
  
  for cnt in contours[::-1]:
      print cv2.arcLength(cnt, True)
      print cnt
      approx = cv2.approxPolyDP(cnt, 0.1*cv2.arcLength(cnt, True), True)
      print len(approx)
      if len(approx) == 5:
          print "pentagon"
          cv2.drawContours(img, [cnt], 0, 255, 2)
          cv2.imshow('tmppentagon', img)
          cv2.waitKey(0)
      elif len(approx) == 3:
          print "triangle"
          cv2.drawContours(img, [cnt], 0, (0, 255, 0), 2)
          cv2.imshow('tmptriangle', img)
          cv2.waitKey(0)
      elif len(approx) == 2:
          print 'approx:'
          print approx
          ret = cv2.matchShapes(cnt, cnt0, 1, 0.0)
          print 'match shape ret:%s' % ret
          print "two approx line"
          cv2.drawContours(img, [cnt], 0, (0, 255, 0), 2)
          cv2.imshow('twoline?', img)
          cv2.waitKey(0)
      elif len(approx) == 4:
  
          ret = cv2.matchShapes(cnt, cnt0, 1, 0.0)
          print 'match shape ret:%s' % ret
          if ret &gt; 0.5:
              print "Parallelogram"
          elif 0.3 &lt; ret &lt; 0.5:
              print "Rectangle"
          elif 0 &lt; ret &lt; 0.3:
              print "Rhombus"
          else:
              print "square"
          print cv2.arcLength(cnt, True)
          print approx
          cv2.drawContours(img, [approx], 0, (0, 0, 255), 2)
          cv2.imshow('tmpsquare', img)
          cv2.waitKey(0)
          if int(cv2.arcLength(cnt, True)) &gt;= 96:
  
              if math.fabs(math.sqrt((approx[0][0][0]-approx[1][0][0])**2+(approx[0][0][1]-approx[1][0][1])**2) - math.sqrt((approx[1][0][0]-approx[2][0][0])**2+(approx[1][0][1]-approx[2][0][1])**2)) &lt;= 5:
                  x, y, w, h = cv2.boundingRect(cnt)
                  cv2.imshow('final',img[y:y+h,x:x+w])
                  cv2.waitKey(0)
              print 'target but long squere detected...'
              cv2.waitKey(0)
      elif len(approx) == 9:
          print "half-circle"
          cv2.drawContours(img,[cnt],0,(255,255,0),2)
          cv2.imshow('tmphalfcircle',img)
          cv2.waitKey(0)
      elif len(approx) &gt; 15:
          print "circle"
          cv2.drawContours(img,[cnt],0,(0,255,255),2)
          cv2.imshow('tmpcircle',img)
          cv2.waitKey(0)
  
  cv2.imshow('img', img)
  cv2.imwrite('tmp.png', img)
  cv2.waitKey(0)
  cv2.destroyAllWindows()
  </code></pre></li>
  </ol>
  
  <h2>Results for the two input images respectively:</h2>
  
  <p>First result:</p>
  
  <p><a href="https://i.stack.imgur.com/McSZT.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/McSZT.png" alt="console out put highlighting zero difference between contours, with highlighted contour area for square for first input image"></a></p>
  
  <p>Second result:</p>
  
  <p><a href="https://i.stack.imgur.com/UJBXZ.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/UJBXZ.png" alt="console out put highlighting 4.21 difference between contours, with highlighted contour area for square for second input image"></a></p>
  
  <h2>Env:</h2>
  
  <p>python 2.7.10</p>
  
  <p>opencv 3.2.0</p>
  
  <h2>Questions:</h2>
  
  <ol>
  <li><p>Why is the length of cv2.approxPolyDP always 2 instead of 4 for both images? I would expect the result to be 4 for the square in the image. </p></li>
  <li><p>Why are my <code>cv2.matchShapes</code> results so different? I think 0 is the ideal output, but why does matching against the second image produce such a high number?</p></li>
  </ol>