title: Python - Detect a QR code from an image and crop using OpenCV
body: <p>I'm working on a project using Python(3.7) and OpenCV in which I have an Image(captured using the camera) of a document with a QR code placed on it.</p>
  
  <p>This QR code has 6 variables respectively as:</p>
  
  <ol>
  <li><p>Size of QR code image</p></li>
  <li><p>Top</p></li>
  <li><p>Right  </p></li>
  <li><p>Bottom</p></li>
  <li><p>Left</p></li>
  <li><p>Unit</p></li>
  </ol>
  
  <hr>
  
  <h2>                                <strong>Latest Update:</strong></h2>
  
  <blockquote>
    <p>Here are the steps I need to perform in the same order:</p>
    
    <ol>
    <li>Detect the qr code &amp; decode it to read size values</li>
    <li>So, if the size of QR-code(image) is not equal to the size which is mentioned inside it then scale the image to equal both size values.</li>
    <li>Then crop the image towards all sides from QR code image according to the values mentioned inside qr code.</li>
    </ol>
    
    <p><strong>I have tried this code:</strong></p>
  </blockquote>
  
  <pre><code>def decodeAndCrop(inputImage):
      print(str(inputImage))
      image = cv2.imread(str(inputImage))
      qrCodeDetector = cv2.QRCodeDetector()
      decodedText, points, _ = qrCodeDetector.detectAndDecode(image)
      qr_data = decodedText.split(",")
      print("qr data from fucntion: {}".format(qr_data))
      if points is not None:
          pts = len(points)
      # print(pts)
      for i in range(pts):
          nextPointIndex = (i + 1) % pts
          if str(inputImage) == "scaled_img.jpg":
              cv2.line(
                  image,
                  tuple(points[i][0]),
                  tuple(points[nextPointIndex][0]),
                  (255, 0, 0),
                  5,
              )
          print(points[i][0])
          width = int(
              math.sqrt(
                  (points[0][0][0] - points[1][0][0]) ** 2
                  + (points[0][0][1] - points[1][0][1]) ** 2
              )
          )
          height = int(
              math.sqrt(
                  (points[1][0][0] - points[2][0][0]) ** 2
                  + (points[1][0][1] - points[2][0][1]) ** 2
              )
          )
          print("height and width after scaling: {} {}".format(height, width))
          if not str(inputImage) == "scaled_img.jpg":
              scaled_img = None
              if width == qr_data[0] and height == qr_data[0]:
                  print("Sizes are equal")
                  # Add the extension values to points and crop
                  y = int(points[0][0][1]) - int(qr_data[1])
                  x = int(points[0][0][0]) - int(qr_data[4])
                  roi = image[
                      y : y + height + int(qr_data[3]), x : x + width + int(qr_data[2])
                  ]
                  scaled_img = cv2.imwrite("scaled_img.jpg", roi)
                  return scaled_img
              else:
                  print(
                      "Width and height  "
                      + str(width)
                      + "x"
                      + str(height)
                      + "  not equal to "
                      + str(qr_data[0])
                      + "x"
                      + str(qr_data[0])
                  )
                  if height &gt; int(qr_data[0]):
                      scale_width = int(width) - int(qr_data[0])
                      scale_height = int(height) - int(qr_data[0])
                      print(f"scaled width: {scale_width} scaled height: {scale_height}")
                      dimension = (scale_width, scale_height)
                      scaled_img = cv2.resize(
                          image, dimension, interpolation=cv2.INTER_AREA
                      )
                      print("new img dims: {}".format(scaled_img.shape))
                      cv2.imshow("scaled image:", scaled_img)
                      cv2.imwrite("scaled_img.jpg", scaled_img)
                  elif height &lt; int(qr_data[0]):
                      scale_width = int(qr_data[0]) - width
                      scale_height = int(qr_data[0] - height)
                      print(f"scaled width: {scale_width} scaled height: {scale_height}")
                      dimension = (scale_width, scale_height)
                      scaled_img = cv2.resize(
                          image, dimension, interpolation=cv2.INTER_AREA
                      )
                      print("new img dims: {}".format(scaled_img.shape))
                      cv2.imshow("scaled image:", scaled_img)
                      cv2.imwrite("scaled_img.jpg", scaled_img)
                      cv2.imshow("final output:", roi)
                  return scaled_img
  
          else:
              y = int(points[0][0][1]) - int(qr_data[1])
              x = int(points[0][0][0]) - int(qr_data[4])
              print(" x and y")
              print(x)
              print(y)
              roi = image[
                  y : y + height + int(qr_data[3]), x : x + width + int(qr_data[2])
              ]
              final_img = cv2.imwrite("finalized_image.jpg", roi)
              cv2.imshow("finalized image:", final_img)
              return final_img
  
  
  if __name__ == "__main__":
      image_to_crop = decodeAndCrop("example_input_1.jpg")
      final_image = decodeAndCrop("scaled_img.jpg")
      cv2.imshow("Cropped:", image_to_crop)
      # cv2.imshow("Final: ", final_image)
      cv2.waitKey(0)
      cv2.destroyAllWindows()
  </code></pre>
  
  <hr>
  
  <blockquote>
    <p>The code above gives an error as:
    final_img = cv2.imwrite("finalized_image.jpg", roi)
    cv2.error: OpenCV(4.2.0) /Users/travis/build/skvark/opencv-python/opencv/modules/imgcodecs/src/loadsave.cpp:715: error: (-215:Assertion failed) !_img.empty() in function 'imwrite'</p>
  </blockquote>
  
  <hr>
  
  <h2>                                <strong>End of Latest Update:</strong></h2>
  
  <hr>
  
  <p>An example decoded information of a QR code is as: 100, 20, 40, 60, 20, px</p>
  
  <p>Now, I need to detect the QR code from this document image and in the first step I need to compare the size of QR code in captured image of document with the size which is mentioned in the decoded information for example if in the captured image the size of the QR image is 90X90px and the size from decoded info is 100X100px we need to compare that.</p>
  
  <p>Then, in the second step I have to crop the complete image by using the Top, Right, Bottom &amp; Left variables accordingly. According to the above example we need to crop the image from the position of detected QR code to 20px Top, 40px Right, 60px Bottom and 20px Right. I have added an example Image below.</p>
  
  <p>I have done to decode the QR code information but how can I take the detected QR code area as a seprate image and compare it's size with the mentioned size and then crop the Image accordingly?</p>
  
  <blockquote>
    <p>Here's what I have tried so far:</p>
  </blockquote>
  
  <pre><code>import cv2
  
  image = cv2.imread('/Users/abdul/PycharmProjects/QScanner/images/second.jpg')
  
  qrCodeDetector = cv2.QRCodeDetector()
  decodedText, points, _ = qrCodeDetector.detectAndDecode(image)
  qr_data = decodedText.split(',')
  qr_size = qr_data[0]
  top = qr_data[1]
  right = qr_data[2]
  bottom = qr_data[3]
  left = qr_data[4]
  
  print(f'Size: {qr_size}' + str(qr_data[5]))
  print(f'Top: {top}')
  print(f'Right: {right}')
  print(f'Bottom: {bottom}')
  print(f'Left: {left}')
  if points is not None:
      pts = len(points)
      print(pts)
      for i in range(pts):
          nextPointIndex = (i+1) % pts
          cv2.line(image, tuple(points[i][0]), tuple(points[nextPointIndex][0]), (255,0,0), 5)
          print(points[i][0])
      print(decodedText)    
      cv2.imshow("Image", image)
      cv2.waitKey(0)
      cv2.destroyAllWindows()
  else:
      print("QR code not detected")
  </code></pre>
  
  <blockquote>
    <p>Here's an example Image:</p>
  </blockquote>
  
  <p><a href="https://i.stack.imgur.com/nFjty.jpg" rel="noreferrer"><img src="https://i.stack.imgur.com/nFjty.jpg" alt="enter image description here"></a></p>
  
  <blockquote>
    <p>and here's a sample of input image:</p>
  </blockquote>
  
  <p><a href="https://i.stack.imgur.com/fjVVD.jpg" rel="noreferrer"><img src="https://i.stack.imgur.com/fjVVD.jpg" alt="enter image description here"></a></p>