Error parsing image in half using Python

5

I'm trying to split an image in half using the code below, but I'm having a return error.

Code:

import cv2
import numpy as np

# Read the image
img = cv2.imread("IMD015.png")
width = img.shape

# Cut the image in half
width_cutoff = width / 2
s1 = img[:, width_cutoff]
s2 = img[:, width_cutoff:]

# Save each half
cv2.imsave("face1.png", s1)
cv2.imsave("face2.png", s2)

i1 = cv2.imread("face1.png")
i2 = cv2.imread("face2.png")
assert i1.mode == i2.mode, "Different kinds of images."
assert i1.size == i2.size, "Different sizes."

pairs = zip(i1.getdata(), i2.getdata())
if len(i1.getbands()) == 1:
    # for gray-scale jpegs
    dif = sum(abs(p1-p2) for p1,p2 in pairs)
else:
    dif = sum(abs(c1-c2) for p1,p2 in pairs for c1,c2 in zip(p1,p2))

ncomponents = i1.size[0] * i1.size[1] * 3
print ("Difference (percentage):"+ str((dif / 255.0 * 100) / ncomponents))

Error:

line 10, in <module>
    width_cutoff = width / 2
TypeError: unsupported operand type(s) for /: 'tuple' and 'int'

I know the error is in the split, but how do I fix it?

    
asked by anonymous 15.11.2018 / 19:25

2 answers

4

The error is very descriptive, you are getting a tuple and trying to divide by 2. You can only divide a number, not a set of data.

The documentation is pretty flawed, but in the end I was able to find that the img.shape variable is even receiving a tuple with some image data. You can not get this tuple, but you can deconstruct it into variables and then pick up one of those variables and divide it if any of the elements are a number, and in fact I was able to infer that it is. So to get the width I should have done this:

_, width, _ = img.shape

Even though I do not need the other elements I need to get them, in the case I used _ to discard them and not create a variable at random.

    
15.11.2018 / 19:42
1

To complement response , other ways to get the width.

.shape of OpenCV

With print() in img.shape , you can check that a tuple is returned as follows: (altura, largura, número_de_canais)

Eg: (600, 800, 3)

Then each value can be obtained with: height, width, channels = img.shape

Access the tuple element that matches the width:

  • w = img.shape[1]
  • w = img.shape[-2]

Or slicing of Python can be used to get only height and width:

  • h, w = img.shape[:2]
  • h, w = img.shape[:-1]

Numpy

Width can be obtained with w = np.size(img, 1)

And height with h = np.size(img, 0)

And the channel with c = np.size(img,2)

PIL

With the Python Imaging Library

from PIL import Image
im = Image.open('3mNqf.png')
print(im.size)
width, height = im.size
w = im.size[0]
w = im.size[-2]
    
16.11.2018 / 16:26