Is noLoop stopping execution of draw?

Viewed 55

This is my first post here, so I apologize if I'm making any mistakes.

I recently started to study Processing in Python mode and I'm trying to develop a code that, after selecting an image from your computer, reads the colors and inserts them in a list. The final idea is to calculate the percentage of certain colors in the image. For this I am using the following code:

img = None
tam=5
cores_img = []


def setup():
    size (500, 500)
    selectInput(u"Escolha a ilustração para leitura de cores", "adicionar_imagens")
    noLoop()

def adicionar_imagens(selection):
    global img
    if selection == None:
        print(u"Seleção cancelada")
    else:
        print(u"Você selecionou " + selection.getAbsolutePath())
        img = loadImage(selection.getAbsolutePath())
                
def draw():
    if img is not None:
        image (img, 0, 0)
        for xg in range(0, img.width, tam):
            x = map(xg, 0, img.width, 0, img.width)
            for yg in range(0, img.height, tam):
                y = map(yg, 0, img.height, 0, img.height)
                cor = img.get(int(x), int(y))
                cores_img.append(cor)
                print (cores_img)

I'm using noLoop() so that the colors are added only once to the list. However, it seems that the draw is not running. It performs the setup actions, but when the image is selected, nothing happens. There is also no error message.

I'm completely lost about what might be happening. If anyone has any ideas and can help, I really appreciate it!

1 Answers

Calling noLoop() indeed stops the draw() loop from running, which means by the time you've selected and image nothing yould happen.

You can however manually call draw() (or redraw()) once the image is loaded:

img = None
tam=5
cores_img = []


def setup():
    size (500, 500)
    selectInput(u"Escolha a ilustração para leitura de cores", "adicionar_imagens")
    noLoop()

def adicionar_imagens(selection):
    global img
    if selection == None:
        print(u"Seleção cancelada")
    else:
        print(u"Você selecionou " + selection.getAbsolutePath())
        img = loadImage(selection.getAbsolutePath())
        redraw()
                
def draw():
    if img is not None:
        image (img, 0, 0)
        for xg in range(0, img.width, tam):
            x = map(xg, 0, img.width, 0, img.width)
            for yg in range(0, img.height, tam):
                y = map(yg, 0, img.height, 0, img.height)
                cor = img.get(int(x), int(y))
                cores_img.append(cor)
                print (cores_img)

You should pay attention to a few details:

  • As the reference mentions, calling get() is slow: pixels[x + y * width] is faster (just remember to call loadPixels() if the array doesn't look right)
  • PImage already has a pixels array: calling img.resize(img.width / tam, img .height / tam) should downsample the image so you can read the same list
  • x = map(xg, 0, img.width, 0, img.width) (and similarly y) maps from one range to the same range which has no effect

e.g.

img = None
tam=5
cores_img = None


def setup():
    size (500, 500)
    selectInput(u"Escolha a ilustração para leitura de cores", "adicionar_imagens")
    noLoop()

def adicionar_imagens(selection):
    global img, cores_img
    if selection == None:
        print(u"Seleção cancelada")
    else:
        print(u"Você selecionou " + selection.getAbsolutePath())
        img = loadImage(selection.getAbsolutePath())
        print("total pixels",len(img.pixels))
        img.resize(img.width / tam, img.height / tam);
        cores_img = list(img.pixels)
        print("resized pixels",len(img.pixels))
        print(cores_img)
                
def draw():
    pass

Update

I thought that calling noLoop on setup would make draw run once. Still it won't print the image... I'm calling 'image (img, 0, 0)' at the end of 'else', on 'def adicionar_imagens (selection)'. Should I call it somewhere else?

  • think of adicionar_imagens time-wise, running separate to setup() and draw()
  • you are right, draw() should be called once (because of noLoop()), however it's called as soon as setup() completes but not later (as navigating the file system, selecting a file and confirming takes time)
  • draw() would need to be forced to run again after the image was loaded

Here's an updated snippet:

img = None
# optional: potentially useful for debugging
img_resized = None
tam=5
cores_img = None


def setup():
    size (500, 500)
    selectInput(u"Escolha a ilustração para leitura de cores", "adicionar_imagens")
    noLoop()

def adicionar_imagens(selection):
    global img, img_resized, cores_img
    if selection == None:
        print(u"Seleção cancelada")
    else:
        print(u"Você selecionou " + selection.getAbsolutePath())
        img = loadImage(selection.getAbsolutePath())
        # make a copy of the original image (to keep it intact)
        img_resized = img.get()
        # resize
        img_resized.resize(img.width / tam, img.height / tam)
        # convert pixels array to python list
        cores_img = list(img.pixels)
        # force redraw
        redraw()
        # print data
        print("total pixels",len(img.pixels))
        print("resized pixels",len(img.pixels))
        # print(cores_img)

def draw():
    print("draw called " + str(millis()) + "ms after sketch started")
    # if an img was selected and loaded, display it 
    if(img != None):
        image(img, 0, 0)
    # optionally display resized image
    if(img_resized != None):
        image(img_resized, 0, 0)
        

Here are a couple of notes that may be helpful:

  • each pixel in the list is a 24 bit ARGB colour (e.g. all channels are stored in a single value). if you need individual colour channels remember you have functions like red(), green(), blue() available. (Also if that gets slow notice the example include faster versions using bit shifting and masking)
  • the Histogram example could be helpful. You would need to port from Java to Python syntax and use 3 histograms (one for each colour channel), however the principle of counting intensities is nicely illustrated

histogram overlaid on image

Related