• 13

A PHP Error was encountered

Severity: Notice

Message: Undefined index: userid

Filename: views/question.php

Line Number: 191


File: /home/prodcxja/public_html/questions/application/views/question.php
Line: 191
Function: _error_handler

File: /home/prodcxja/public_html/questions/application/controllers/Questions.php
Line: 433
Function: view

File: /home/prodcxja/public_html/questions/index.php
Line: 315
Function: require_once

name Punditsdkoslkdosdkoskdo

numpy uint8 pixel wrapping solution

For an image processing class, I am doing point operations on monochrome images. Pixels are uint8 [0,255].

numpy uint8 will wrap. For example, 235+30 = 9. I need the pixels to saturate (max=255) or truncate (min=0) instead of wrapping.

My solution uses int32 pixels for the point math then converts to uint8 to save the image.

Is this the best way? Or is there a faster way?


import sys
import numpy as np
import Image

def to_uint8( data ) :
    # maximum pixel
    latch = np.zeros_like( data )
    latch[:] = 255
    # minimum pixel
    zeros = np.zeros_like( data )

    # unrolled to illustrate steps
    d = np.maximum( zeros, data )
    d = np.minimum( latch, d )

    # cast to uint8
    return np.asarray( d, dtype="uint8" )

img = Image.open(infilename)
data32 = np.asarray( img, dtype="int32")
data32 += 30
data_u8 = to_uint8( data32 )
outimg = Image.fromarray( data_u8, "L" )
outimg.save( "out.png" )

Input image:

Output image:

      • 1
    • While working with the MNIST dataset my resulting .png images showed weird square artifacts instead of the actual handwritten number. The issue was also the dtype int32. After using the accepted answer with numpy.clip and the astype() conversion everything worked.

Use numpy.clip:

import numpy as np
np.clip(data32, 0, 255, out=data32)
data_u8 = data32.astype('uint8')

Note that you can also brighten images without numpy this way:

import ImageEnhance
enhancer = ImageEnhance.Brightness(img)
outimg = enhancer.enhance(1.2)
  • 37
Reply Report
    • np.clip() is exactly what I've been needing. Thanks! I'll also read up on ImageEnhance. The homework was about doing point ops ourselves but will be good to learn other ways.

You can use OpenCV add or subtract functions (additional explanation here).

>>> import numpy as np
>>> import cv2
>>> arr = np.array([100, 250, 255], dtype=np.uint8)
>>> arr
Out[1]: array([100, 250, 255], dtype=uint8)
>>> cv2.add(arr, 10, arr)  # Inplace
Out[2]: array([110, 255, 255], dtype=uint8)  # Saturated!
>>> cv2.subtract(arr, 150, arr)
Out[3]: array([  0, 105, 105], dtype=uint8)  # Truncated!

Unfortunately it's impossible to use indexes for output array, so inplace calculations for each image channel may be performed in this, less efficient, way:

arr[..., channel] = cv2.add(arr[..., channel], 40)
  • 6
Reply Report

Basically, it comes down to checking before you add. For instance, you could define a function like this:

def clip_add(arr, amt):
    if amt > 0:
        cutoff = 255 - amt
        arr[arr > cutoff] = 255
        arr[arr <= cutoff] += amt
        cutoff = -amt
        arr[arr < cutoff] = 0
        arr[arr >= cutoff] += amt
  • 1
Reply Report

Trending Tags