My end goal is to find a color in an image (in this case white) and replace it with another color (based on certain circumstances). So, as a certain variable changes the white is replaced with a specific color.
However, to get there I'm currently just playing with images (using tutorials ..etc). I'm trying to use the below code to print the color palette of an image. My understanding is the colors are a "tuple" of 3 integer representing RGB. 0 = darkest, 255 = white. So, the image I'm testing is a black and white image. I'm expecting something like "(0,0,0),(255,255,255)". So, I figured if I could get this far, then I could write a code to replace the "(255,255,255)" with the appropriate color.
I mentioned the end goal because I'm very aware that my approach might not be the best, and that perhaps someone has a better way I can go about this. If not, I'd at least like to be able to print a string referencing the colors an image contains. The "NOFRAME" was a great piece of advice I found on this site, as I'm not actually "using" the images/graphics - just using their attributes.
image1=r"C:\Python27\Lib\site-packages\pygame\examples\data\image1.jpg"
image2=r"C:\Python27\Lib\site-packages\pygame\examples\data\image2.png"
import pygame, sys
from pygame.locals import *
pygame.init()
pygame.display.set_mode((1,1), pygame.NOFRAME)
background = pygame.image.load(image1).convert()
mouse_c=pygame.image.load(image2).convert_alpha()
colorpal = pygame.Surface.get_palette(mouse_c)
print colorpal
What you want to do is going to require a lot of pixel level work, so I recommend that you use a pygame.PixelArray object for direct pixel access of the surface(s).
For what you specifically want to do, it sounds like you could use the pygame.PixelArray.replace() method.
You can get individual pixels on image surfaces by using theget_atmethod of Pygame surfaces - as inmouse_c.get_at((0,0)).
This is strictly what you are asking for -- but it won't suit any real world needs, as it is extremely, and I am saying extremely, slow to process all pixels of an image calling just this.
You could take the image buffer withget_bufferand interpret the data there, raw, or pass the buffer along to a function written in native code to get some speed.
Still, if your goal is to replace a color by another in real time you can resort to use indexed images - that way, each image will have a color table, you just modify,say, the color number 10 to be 0,0,255, and as you render the image, all occurrences of that color become blue. This is fast -- not as efficient as back in the 8 bit video-games time when this was done by hardware -- but it will be orders of magnitude faster any substitutions you try to make in pure Python code.
Related
For an analysis, I'd like to take the a bunch of TIF images I have, and fill in the black background to create a perfect square.
I would like to keep the same general pattern of the image when I fill in the black spots, instead of just filling in the black with random bits of white and blue. My first thought for doing this is to impose some sort of symmetrical "reflection" of the image onto the black portions - the concept is detailed below.
The thing is, I'm not sure how to go about this - my first thought was to convert the image to a NumPy array and copy the individual rows of pixels over for a pseudo-reflection, but that could take a lot of time since I would be accounting for the length of the black portion in each row, and it wouldn't even be the desired result. I was wondering if there was a package or method that did something like this already, perhaps in PIL.
Any ideas are appreciated, as I am not to familiar with image processing in Python (or in general) - thank you!
EDIT: Here is a google drive link for the example image in question.
EDIT 2: Here is a google drive link for another example, this time with two "overlapping" black background areas (in other words, the actual data has a corner)
so, as the topic says, I want to write some text on an transparent image.
Or, to be more specific, I want to write on multiple specific positions different text. The point is, I want to use a custom font (coolvetica) and (and there is my problem) I want it to be anti-aliased. unfortunately, PIL does not support font-anti-aliasing, as you might already know, but also see here:
PIL example image.
So as you see, PIL has not only an issue with the coordinates, but also does not really support font-anti-aliasing and adds some irritating black-ish border to the text. It is not very usable for me.
So after some searching, I found Python Wand. The output is a lot better, but the antialiasing leads not to the result I want: Wand example image. The curves are not as smooth as I want and there are some weird "pimples" like the dot at the end of the "r".
My code to use wand is this:
with Drawing() as draw:
with wandimage(filename="Skispringen_Score.png") as img:
draw.font_family = 'coolvetica.ttf'
draw.text_antialias = True
draw.fill_color = (Color("rgba(255, 255, 255, 255)"))
for postionName, scorePosition in scoreContent.items():
if isinstance(currentScoreText[postionName], int) and currentScoreText[postionName] > 9:
center = 2
else:
center = 0
draw.font_size = fontsize[scorePosition["size"]]
draw.text(scorePosition["x"] - center, scorePosition["y"], str(currentScoreText[postionName]))
draw(img)
img.save(filename='wand-image.png')
And here is an example of what the text should actually look like: PHP example image.
This image was generated with php and the text looks as smooth as I want to.
I also tried to use cairo, but the documentation is really not that good (especially examples are rare) and I just don't even know how to write any text with it nor how to set an custom font.
The actual output image has an resolution of 1280x720 and is - besides of the text - completely transparent, the image is just an overlay for an videostream.
Do you have any idea how to get a nice looking text onto the image with python?
You could try pycairo. Here are some code examples https://github.com/pygobject/pycairo/tree/master/examples
The reference docs for cairo are for C.
If you want even better results then you could render the image at 4 times the size and
downsample it to the desired size.
You can also try some filters like a gaussian blur.
For pixel perfect images you will have to use the same rendering engine that your php function is using.
I want to programmatically modify a bitmap using python but don't really need a thorough grounding in the subject, so would like to concentrate on learning just what I need to get the job done.
A good example of the kind of thing I'm after would be a bitmap image of england and it's counties. This would initially display a black border around all the counties on a white background.
So far so good, but how can I dynamically change the background color of a county?
Off the top of my head I was thinking I might find a flood-fill routine that works similar to a simple paint app. Something that changes all the pixels within an area enclosed by a specified color. I've had a quick look at the PIL documentation but didn't find anything I recognised as a flood fill function?
I don't yet know exactly what a mask is or how to use it but maybe this is an avenue I should explore. Maybe I could define a mask for each county and then use the mask to guide the fill process? Can masks be defined and stored within the bitmap for later use by my program?
Same goes for paths???
Any help or pointers would be greatly appreciated.
PIL has an undocumented function ImageDraw.floodfill:
>>> import ImageDraw
>>> help(ImageDraw.floodfill)
Help on function floodfill in module ImageDraw:
floodfill(image, xy, value, border=None)
Fill bounded region.
(Flood-filling should generally be a last resort because it interacts poorly with anti-aliased lines. It is usually better to get the actual boundary data for the counties and then draw a filled polygon. However, PIL doesn't support anti-aliased line drawing so this advice is useless unless you switch your drawing module to something more capable like PythonMagick or pycairo.)
You can try the opencv binding in python. Here is some example: http://opencv.willowgarage.com/documentation/python-introduction.html
You can then use the cvFloodFill function to flood fill a region.
How can I replace a colour across multiple images with another in python? I have a folder with 400 sprite animations. I would like to change the block coloured shadow (111,79,51) with one which has alpha transparencies. I could easily do the batch converting using:
img = glob.glob(filepath\*.bmp)
however I dont know how I could change the pixel colours. If it makes any difference, the images are all 96x96 and i dont care how long the process is. I am using python 3.2.2 so I cant really use PIL (I think)
BMP is a windows file format, so you will need PIL or something like it; or you can roll your own reader/writer. The basic modules won't help as far as I'm aware. You can read PPM and GIF using Tk (PhotoImage()) which is part of the standard distribution and use get() and put() on that image to change pixel values. See references online, because it's not straight-forward - the pixels come from get() as 3-tuple integers, but need to go back to put() as space-separated hex text!
Are your images in indexed mode (8 bit per pixel with a palette),or "truecolor" 32bpp images? If they are in indexed modes, it would not be hard to simply mark the palette entry for that color to be transparent across all files.
Otherwise, you will really have to process all pixel data. It also could be done by writting a Python script for GIMP - but that would require Python-2 nonetheless.
I have photo images of galaxies. There are some unwanted data on these images (like stars or aeroplane streaks) that are masked out. I don't just want to fill the masked areas with some mean value, but to interpolate them according to surrounding data. How do i do that in python?
We've tried various functions in SciPy.interpolate package: RectBivariateSpline, interp2d, splrep/splev, map_coordinates, but all of them seem to work in finding new pixels between existing pixels, we were unable to make them fill arbitrary "hole" in data.
What you want is called Inpainting.
OpenCV has an inpaint() function that does what you want.
What you want is not interpolation at all. Interpolation depends on the assumption that data between known points is roughly contiguous. In any non-trivial image, this will not be the case.
You actually want something like the content-aware fill that is in Photoshop CS5. There is a free alternative available in The GIMP through the GIMP-resynthesize plugin. These filters are extremely advanced and to try to re-implement them is insane. A better choice would be to figure out how to use GIMP-resynthesize in your program instead.
I made my first gimp python script that might help you:
my scripts
It is called conditional filter as it is a matrix filter that fill all transparent pixels from an image according to the mean value of its 4 nearest neighbours that are not transparent.
Be sure to use a RGBA image with only 0 and 255 transparent values.
Its is rough, simple, slow, unoptimized but bug free.