1

I'm trying to accomplish a basic image processing. Here is my algorithm :

Find n., n+1., n+2. pixel's RGB values in a row and create a new image from these values.

Algorithm

Here is my example code in python :

import glob
import ntpath
import time
from multiprocessing.pool import ThreadPool as Pool

import matplotlib.pyplot as plt
import numpy as np
from PIL import Image

images = glob.glob('model/*.png')
pool_size = 17


def worker(image_file):
    try:
        new_image = np.zeros((2400, 1280, 3), dtype=np.uint8)
        image_name = ntpath.basename(image_file)
        print(f'Processing [{image_name}]')

        image = Image.open(image_file)
        data = np.asarray(image)

        for i in range(0, 2399):
            for j in range(0, 1279):
                pix_x = j * 3 + 1
                red = data[i, pix_x - 1][0]
                green = data[i, pix_x][1]
                blue = data[i, pix_x + 1][2]
                new_image[i, j] = [red, green, blue]

        im = Image.fromarray(new_image)
        im.save(f'export/{image_name}')
    except:
        print('error with item')


pool = Pool(pool_size)
for image_file in images:
    pool.apply_async(worker, (image_file,))

pool.close()
pool.join()

My input and output images are in RGB format. My code is taking 5 second for every image. I'm open for any idea to optimization this task.

Here is example input and output images :

Input Image2 [ 3840 x 2400 ]

Output Image3 [ 1280 x 2400 ]

4
  • Include the pic in the question, not as link. Commented Sep 23, 2020 at 11:07
  • This is well answered by @Lukáš-Lalinský [link]stackoverflow.com/questions/29581014/…, you want to avoid per-pixel loops in Python. They will always be slow. To get somewhat fast image processing, you need to get used to working with matrices instead of individual pixels. You have basically two options, you can either use NumPy or OpenCV, or a combination of the two... Commented Sep 23, 2020 at 11:10
  • So your output image is 1/3 width and 1/3 the height of your input image? Please show input and output images. Commented Sep 23, 2020 at 11:53
  • added example input and output images Commented Sep 23, 2020 at 11:56

2 Answers 2

1

Here is an approach:

import cv2
import numpy as np

# Load input image
im = cv2.imread('input.png')

# Calculate new first layer - it is every 3rd pixel of the first layer of im
n1 = im[:, ::3, 0]

# Calculate new second layer - it is every 3rd pixel of the second layer of im, starting with an offset of 1 pixel
n2 = im[:, 1::3, 1]

# Calculate new third layer - it is every 3rd pixel of the third layer of im, starting with an offset of 2 pixels
n3 = im[:, 2::3, 2]

# Now stack the three new layers to make a new output image
res = np.dstack((n1,n2,n3))
Sign up to request clarification or add additional context in comments.

4 Comments

dstack is compression on both axis. is it possible to compress only one axis ?
hstack appends images side-by-side horizontally. vstack appends images one above the other vertically. dstack stacks images by channels, or depthwise. No compression involved. It is the same as np.stack(..., axis=2, ...)
By the way, if you are happier writing loops, you could look at numba, example here stackoverflow.com/a/55356126/2836621
By the way, threads don't buy you much with Python as, apart from I/O, only one thread will be active at a time because of the GIL. You may therefore want multiprocessing rather than multithreading. Try watching your CPUs with htop or Process Monitor while processing to see if all cores are 100% busy.
0

As far as I understood from the question, you want to shift the pixel values of each channel of the input image in the output image. So, here is my approach.

im = cv2.cvtColor(cv2.imread('my_image.jpg'), cv2.COLOR_BGR2RGB)
im = np.pad(im, [(3, 3),(3,3),(0,0)], mode='constant', constant_values=0) # Add padding for enabling the shifting process later

r= im[:,:,0]

g= im[:,:,1]
g = np.delete(g,np.s_[-1],axis=1) # remove the last column
temp_pad = np.zeros(shape=(g.shape[0],1)) # removed part
g = np.concatenate((temp_pad,g),axis=1) # put the removed part back


b = im[:,:,2]
b = np.delete(b,np.s_[-2::],axis=1) # remove the last columns
temp_pad = np.zeros(shape=(b.shape[0],2)) # removed parts
b = np.concatenate((temp_pad,b),axis=1) # put the removed parts back


new_im = np.dstack((r,g,b)) # Merge the channels
new_im = new_im[3:-3,3:-3,:]/np.amax(new_im)#*255 # Remove the padding

Basically, I achieved the shifting by padding&merging the green and blue channels. Let me know if this is what you are looking for. Kolay gelsin :)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.