Change a pixel value - python

I have an image that I opened using LoadImageM and I get the pixel data using Get2D put I can't seem to find any built-in function to change a pixel value.
I've tried using multiple things from Rectangle to CV_RGB but with no successful results.

Consider checking out the new version of the opencv library.
You import it with
import cv2
and it directly returns numpy arrays.
So for example if you do
image_array = cv2.imread('image.png')
then you can just access and change the pixels values by simply manipulating image_array :
image_array[0,0] = 100
sets the top left pixel to the value to 100.
Depending on your installation, you may already have the cv2 bindings, so check if import cv2 works.
Otherwise just install opencv and numpy and you are good to go.

Related

How to remove noise from an image using pillow?

I am trying to de-noise an image that I've made in order to read the numbers on it using Tesseract.
Noisy image.
Is there any way to do so?
I am kind of new to image manipulation.
from PIL import ImageFilter
im1 = im.filter(ImageFilter.BLUR)
im2 = im.filter(ImageFilter.MinFilter(3))
im3 = im.filter(ImageFilter.MinFilter)
The Pillow library provides the ImageFilter module that can be used to enhance images. Per the documentation:
The ImageFilter module contains definitions for a pre-defined set of filters, which can be be used with the Image.filter() method.
These filters work by passing a window or kernel over the image, and computing some function of the pixels in that box to modify the pixels (usually the central pixel)
The MedianFilter seems to be widely used and resembles the description given in nishthaneeraj's answer.
You have to read Python pillow Documentation
Python pillow Documentation link:
https://pillow.readthedocs.io/en/stable/
Pillow image module:
https://pillow.readthedocs.io/en/stable/reference/ImageFilter.html#module-PIL.ImageFilter
How do you remove noise from an image in Python?
The mean filter is used to blur an image in order to remove noise. It involves determining the mean of the pixel values within a n x n kernel. The pixel intensity of the center element is then replaced by the mean. This eliminates some of the noise in the image and smooths the edges of the image.

skimage max image resolution (memoryerror)

At the moment i'm using scikit-image as a way to process my images in python. But after some testing I found out that scikit-image doesn't work with images which have a to high resolution. I tried to use a image with a resolution of 3024 x 4032 but it results in a MemoryError error. This happens on multiple different methods provided by scikit-image.
I've found out that it does work if I downscale the image to a way lower resolution. I want to know the maximum allowed resolution is so that I can downscale my images without losing too much of it's quality. And that I can check if a resolution is too big.
I found the real cause of the problem. It's not the resolution but rather scikit-image who changes the datatype of the image to a float which makes it way too big for the memory stack.
A way to get around this is to turn your image in a numpy array with the datatype uint8. Like this:
from PIL import Image
import numpy as np
from skimage.color import rgb2gray
im = Image.open("test.jpg")
pix = np.array(im, dtype=np.uint8)
img = rgb2gray(pix)
after converting it to a numpy array, you can use it for any operation provided by scikit-image
Your workaround is fine, but I would have done it like this:
from skimage import io
from skimage import img_as_ubyte
img = img_as_ubyte(io.imread('test.jpg', as_grey=True))

Changing of pixel values after writing the same image using imwrite opencv python function

import cv2
import numpy as np
im=cv2.imread('test.jpg')
cv2.imwrite('result.jpg',im)
Here test.jpg have size 19 KB and result.jpg have 41 KB even though they are same images.
I observed that there is change in the pixel values of these two images.
How to prevent this one ?
Re-writing or 'saving' an image in any library or tool will always create a new file or 'new pixel values'. This happens because the image is being processed for saving at a certain quality. The saved image quality and size depends on the library doing the save. So default values, depth, compression, etc. need to be provided.
If you just want to create a copy of the image in a new file, either copy the file directly via sys or binary read the whole file and write it to a new one - without using any image processing libs.

How do you display a 2D numpy array in glade-3 ?

I'm making live video GUI using Python and Glade-3, but I'm finding it hard to convert the Numpy array that I have into something that can be displayed in Glade. The images are in black and white with just a single value giving the brightness of each pixel. I would like to be able to draw over the images in the GUI so I don't know whether there is a specific format I should use (bitmap/pixmap etc) ?
Any help would be much appreciated!
In the end i decided to create a buffer for the pixels using:
self.pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,0,8,1280,1024)
I then set the image from the pixel buffer:
self.liveImage.set_from_pixbuf(self.pixbuf)
I think these are the steps you need:
use scipy.misc.toimage to convert your array to a PIL image
check out the answer to this question to convert your PIL image to a cairo surface
use gdk_pixbuf_get_from_surface to convert this to a pixbuf (I don't know it's name in the python api)
make a Gtk.Image out of this using Gtk.Image.new_from_pixbuf
I'm sorry it needs so many conversion steps.

Python matplotlib imshow is slow

I want to display an image file using imshow. It is an 1600x1200 grayscale image and I found out that matplotlib uses float32 to decode the values. It takes about 2 seconds to load the image and I would like to know if there is any way to make this faster. The point is that I do not really need a high resolution image, I just want to mark certain points and draw the image as a background. So,
First question: Is 2 seconds a good performance for such an image or
can I speed up.
Second question: If it is good performance how can I make the process
faster by reducing the resolution. Important point: I still want the
image to strech over 1600x1200 Pixel in the end.
My code:
import matplotlib
import numpy
plotfig = matplotlib.pyplot.figure()
plotwindow = plotfig.add_subplot(111)
plotwindow.axis([0,1600,0,1200])
plotwindow.invert_yaxis()
img = matplotlib.pyplot.imread("lowres.png")
im = matplotlib.pyplot.imshow(img,cmap=matplotlib.cm.gray,origin='centre')
plotfig.set_figwidth(200.0)
plotfig.canvas.draw()
matplotlib.pyplot.show()
This is what I want to do. Now if the picture saved in lowres.png has a lower resolution as 1600x1200 (i.e. 400x300) it is displayed in the upper corner as it should. How can I scale it to the whole are of 1600x1200 pixel?
If I run this program the slow part comes from the canvas.draw() command below. Is there maybe a way to speed up this command?
Thank you in advance!
According to your suggestions I have updated to the newest version of matplotlib
version 1.1.0svn, checkout 8988
And I also use the following code:
img = matplotlib.pyplot.imread(pngfile)
img *= 255
img2 = img.astype(numpy.uint8)
im = self.plotwindow.imshow(img2,cmap=matplotlib.cm.gray, origin='centre')
and still it takes about 2 seconds to display the image... Any other ideas?
Just to add: I found the following feature
zoomed_inset_axes
So in principle matplotlib should be able to do the task. There one can also plot a picture in a "zoomed" fashion...
The size of the data is independent of the pixel dimensions of the final image.
Since you say you don't need a high-resolution image, you can generate the image quicker by down-sampling your data. If your data is in the form of a numpy array, a quick and dirty way would be to take every nth column and row with data[::n,::n].
You can control the output image's pixel dimensions with fig.set_size_inches and plt.savefig's dpi parameter:
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np
data=np.arange(300).reshape((10,30))
plt.imshow(data[::2,::2],cmap=cm.Greys)
fig=plt.gcf()
# Unfortunately, had to find these numbers through trial and error
fig.set_size_inches(5.163,3.75)
ax=plt.gca()
extent=ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
plt.savefig('/tmp/test.png', dpi=400,
bbox_inches=extent)
You can disable the default interpolation of imshow by adding the following line to your matplotlibrc file (typically at ~/.matplotlib/matplotlibrc):
image.interpolation : none
The result is much faster rendering and crisper images.
I found a solution as long as one needs to display only low-resolution images. One can do so using the line
im = matplotlib.pyplot.imshow(img,cmap=matplotlib.cm.gray, origin='centre',extent=(0,1600,0,1200))
where the extent-parameter tells matplotlib to plot the figure over this range. If one uses an image which has a lower resolution, this speeds up the process quite a lot. Nevertheless it would be great if somebody knows additional tricks to make the process even faster in order to use a higher resolution with the same speed.
Thanks to everyone who thought about my problem, further remarks are appreciated!!!

Categories

Resources