Ask Your Question
0

OpenCV Python on RPi, can't seem to iterate through image width [closed]

asked 2018-02-13 06:16:50 -0600

AcrimoniousMirth gravatar image

updated 2018-02-13 08:52:56 -0600

Hi all, Expect to see me here a bit in the next few weeks, working on my university honours project. I'm rewriting a C++ script using OpenCV that I made a year ago but this time in Python. import cv2 as cv import numpy as np from matplotlib import pyplot as plt image = cv.imread('/home/pi/Desktop/ScannerDev/TestImage.png', cv.IMREAD_GRAYSCALE)

#ret, discrImage = cv.threshold(image,127,255,0)

def imageToPoints (image):
    discrImage = cv.threshold (image, 127, 255, 0)

    # Add a line of white values along the top of the image.
    # This ensure that the binary outside contour generation works.
    # It is removed later before points are written to point cloud.
    for x in range (discrImage.cols):
        # Set image x,0 = 255
        discrImage[x,0] = [255,255,255]

    return discrImage

 while (1):
    discrImage = imageToPoints (image)
    cv.imshow ('original', image)
    cv.imshow ('thresholded', discrImage)
    k = cv.waitKey(5) & 0xFF
    if k == 27:
        break

cv.destroyAllWindows()

At the moment I'm working back up from examples online. It seems to all work fine up to this section: # Add a line of white values along the top of the image. # This ensure that the binary outside contour generation works. # It is removed later before points are written to point cloud. for x in range (discrImage.cols): # Set image x,0 = 255 discrImage[x,0] = [255,255,255]

For some reason discrimage.cols and discrimage.width don't seem to work. I get the following printout: Traceback (most recent call last): File "I2LTEST3.py", line 21, in <module> discrImage = imageToPoints (image) File "I2LTEST3.py", line 14, in imageToPoints for x in range (discrImage.cols): AttributeError: 'tuple' object has no attribute 'cols'

Any ideas? Thanks!


EDIT


So thanks to some guidance I've managed to get the code to work for this much:

def imageToPoints (image):
    ret, discrImage = cv.threshold (image, 127, 255, 0)
    height, width = discrImage.shape

    # Add a line of white values along the top of the image.
    # This ensure that the binary outside contour generation works.
    # It is removed later before points are written to point cloud.
    for x in range (width):
        #discrImage[x,0] = 255

    return discrImage

Uncommenting discrImage[x,0] = 255 gives the feedback:

Traceback (most recent call last):
  File "I2LTEST3.py", line 21, in <module>
    discrImage = imageToPoints (image)
  File "I2LTEST3.py", line 16, in imageToPoints
    discrImage[x,0] = 255
IndexError: index 480 is out of bounds for axis 0 with size 480

Which sounds like a range issue, which I'm going to look into further.

edit retag flag offensive reopen merge delete

Closed for the following reason the question is answered, right answer was accepted by AcrimoniousMirth
close date 2018-02-13 08:54:26.652901

Comments

ret, discrImage = cv.threshold(image,127,255,0)

(you had it already correct in the commented part !)

berak gravatar imageberak ( 2018-02-13 07:41:33 -0600 )edit

Hi, I've been flitting about all over so haven't actually discovered what ret, actually does. I thought it was a specific way of returning the value even though it seems laid out as an argument assignment? So after getting that to work I commented it out and tried it with "return" at the end of the function. Would you mind explaining it to me while I give this a go? Thanks :)

AcrimoniousMirth gravatar imageAcrimoniousMirth ( 2018-02-13 07:44:35 -0600 )edit

ret is the threshold value (calculated, if you use THRESH_OTSU) see docs, please

berak gravatar imageberak ( 2018-02-13 08:30:06 -0600 )edit

I read that it returns true or false value from getting the frame here. I'll spend some more time wrapping my head around the actual point if it, which the documentation hasn't made clear to me.

AcrimoniousMirth gravatar imageAcrimoniousMirth ( 2018-02-13 08:37:45 -0600 )edit

^^ that's a different function and a different set of return values.

berak gravatar imageberak ( 2018-02-13 08:41:20 -0600 )edit

Point taken! Thanks for your help. I've debugged right through to some IndexError shown in the edit.

AcrimoniousMirth gravatar imageAcrimoniousMirth ( 2018-02-13 08:51:39 -0600 )edit

both opencv and numpy are row-major, so you have to index it like: discrImage[y,x]

but you should better avoid writing loops like that, and use a numpy slice, so you can assign the whole 1st row in a single line of code:

discrImage[0,:] = 255 # 1st row, and the whole x range
berak gravatar imageberak ( 2018-02-13 08:53:24 -0600 )edit

No matter, solved it :) Many thanks!!

AcrimoniousMirth gravatar imageAcrimoniousMirth ( 2018-02-13 08:54:04 -0600 )edit

Yeah, I just noticed that. It's odd because the same layout [x,y] worked in C++. I'll try the code you suggested, looks way neater, thank you!

Next I need to work with contours and I'm just reading through the documentation but I expect some issues too; kind of common when you're self-taught and in the deep end :')

AcrimoniousMirth gravatar imageAcrimoniousMirth ( 2018-02-13 09:00:13 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
0

answered 2018-02-13 07:24:00 -0600

Tetragramm gravatar image

It's python, so the OpenCV Mat is actually a numpy object. Check the tutorial HERE for how to do basic operations on the image.

edit flag offensive delete link more

Comments

I did, wasn't helpful.

AcrimoniousMirth gravatar imageAcrimoniousMirth ( 2018-02-13 07:36:39 -0600 )edit

See where it says:

b,g,r = cv.split(img)

I followed that but with "h, w = cv.shape(discrImage)" in order to :

for x in range(w):

But doesn't work. I'll try again and give the output

AcrimoniousMirth gravatar imageAcrimoniousMirth ( 2018-02-13 07:40:13 -0600 )edit

def imageToPoints (image): ret, discrImage = cv.threshold (image, 127, 255, 0) height, width = discrImage.shape

    # Add a line of white values along the top of the image.
    # This ensure that the binary outside contour generation works.
    # It is removed later before points are written to point cloud.
    for x in range (width):
        # Set image x,0 = 255
        discrImage[x,0] = [255]

    return discrImage

gave:

    Traceback (most recent call last):
 File "I2LTEST3.py", line 22, in <module>
    discrImage = imageToPoints (image)
  File "I2LTEST3.py", line 17, in imageToPoints
    discrImage[x,0] = [255]
ValueError: setting an array element with a sequence.
AcrimoniousMirth gravatar imageAcrimoniousMirth ( 2018-02-13 07:51:19 -0600 )edit

Okay, so it works this far:

def imageToPoints (image):
    ret, discrImage = cv.threshold (image, 127, 255, 0)
    height, width = discrImage.shape
    """
    # Add a line of white values along the top of the image.
    # This ensure that the binary outside contour generation works.
    # It is removed later before points are written to point cloud.
    for x in range (width):
        # Set image x,0 = 255
        discrImage[x,0] = [255]"""

    return discrImage

Meaning that discrImage.shape worked properly! The error is somewhere in how the for loop is set up. I'll run one or two more tests but pretty sure the previous comment has it down pat. Unsure how to remedy.

AcrimoniousMirth gravatar imageAcrimoniousMirth ( 2018-02-13 08:25:04 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2018-02-13 06:16:50 -0600

Seen: 442 times

Last updated: Feb 13 '18