Why are histograms the same [python + simplecv] - python

My question is why are the two histograms in following code the same.
Because the picture does change, first show shows original picture and second shows completely black picture.
Am I miss-using simpleCV or is this perhaps a bug?
Code:
from itertools import product
from SimpleCV import Image
from SimpleCV import Color
if __name__ == '__main__':
pass
def number_of_hues(picture):
image = Image(picture)
#convert the picture's space to HSV
image = image.toHSV()
image.show()
original_histogram = image.histogram()
(image_x_length, image_y_length) = image.size()
for i,j in product(range(image_x_length), range(image_y_length)):
image[i,j] = Color.BLACK
image.show()
new_histogram = image.histogram()
for o,n in zip(original_histogram, new_histogram):
if o != n:
print o,n

When was the last time you did a pull from the develop github repo? There was a bug in the set item call for the image class that kept images from getting set directly. It was fixed a couple weeks ago. Generally you should try to avoid directly looping over image objects and setting pixels directly as it can be really slow. If you think you found a bug please submit an issue to our github repo and we will try to address it as soon as we can.

Related

Is there a way to get an RGB value of a pixel on a frame of a GIF in PIL?

I am currently working on a discord bot with Pycord. I am working on adding support for GIF images on the currently existing image commands, and I need the color of the pixels. When I try to get the color of an exact point in PIL/Pillow, I get a number representing the color of the pixel in the GIF color table, which is not what I want. Even when I convert the image to RGBA, I still get only the index, nothing else. When I google it, all I see is multitudes of this same method that I tried.
Here is a basic program to demonstrate what I have tried:
from io import BytesIO as toimg
from PIL import Image, ImageFont, ImageDraw, ImageOps, ImageSequence
#reqdata is gif data from a url
imggif = Image.open(toimg(reqdata.content))
for frame in ImageSequence.Iterator(imggif):
img = frame.convert("RGBA")
img = img.convert("RGBA") # might not need this due to the line above but idk
img = ImageOps.grayscale(img) # this line was not here before, edited it in.
width, height = img.size
for y in range(height):
for x in range(width):
print(img.getpixel((x,y))) # this prints out only one number, i need an RGBA value (4 numbers)
If anyone can help, that would be very appreciated!
Edit: I found out the solution and I realized that it was not the frame itself, but instead it was because I grayscaled the image after converting it. The program was created based on what I thought was the mistake, and I didn't even check it! This was nowhere in the question and i apologize for not thinking to look at such a simple thing before posting this question. I had to convert back to RGBA after grayscaling the image. :(
Edit 2: I am just now realizing that this is going to be my very last question, and that I should have looked further to realize my incredibly simple mistake before wasting my last chance on this site i will ever have. It's for the better, I'm a dumbass who is unable to realize such simple things. I will not be and have not been needed on this site.
Try
r, g, b, a = img.getpixel((x, y))
I tested this and it works for me. Based on [this post].
(Get pixel's RGB using PIL)
Edit: another approach that has worked for me in the past is to use pixels = img.load() and index a pixel like pixels[x, y]
This worked for me
from PIL import Image
red_image = Image.open("red.png")
red_image_rgb = red_image.convert("RGB")
rgb_pixel_value = red_image_rgb.getpixel((10,15))
print(rgb_pixel_value) #Prints (255, 0, 0)

Why does the search image in my code doesn't work?

This is my code:
import pyautogui
images = ['colordonkergrijsDCphrasev2.png'] #the image I want it to find
while True:
for image in images: #search for the image in images
pos = pyautogui.locateOnScreen(image, region=(740,870, 50, 20)) #search on the screen for the image
if pos is not None: # this checks that the image was found
pyautogui.click(pos) # click the position of the image
I want that my code clicks on a special region when he is seeing that image.
But my code doesn't do that, my code clicks every time also when the image isn't there. The image I'm using is very similar as the background. But I added confidence = 1 and it still doesn't work
Does someone know how to fix it?
I use Python 3.9.4 64-bit.
I already read the docs but there isn't anything in there what can help me.
If you want to docs here it is: https://pyautogui.readthedocs.io/en/latest/screenshot.html

Python: SVG to PNG converting issue

UPDATE: I tried increasing size in the chess.svg.board and it somehow cleared all the rendering issues at size = 900 1800
I tried using the svglib and reportlab to make .png files from .svg, and here is how the code looks:
import sys
import chess.svg
import chess
from svglib.svglib import svg2rlg
from reportlab.graphics import renderPM
board = chess.Board("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR")
drawing = chess.svg.board(board, size=350)
f = open('file.svg', 'w')
f.write(drawing)
drawing = svg2rlg("file.svg")
renderPM.drawToFile(drawing, "file.png", fmt="png")
If you try to open file.png there is a lot of missing parts of the image, which i guess are rendering issues. How can you fix this?
Sidenote: also getting a lot of 'x_order_2: colinear!' messages when running this on a discord bot, but I am not sure if this affects anything yet.
THIS!! I am having the same error with the same libraries... I didn't find a solution but just a workaround which probably won't help too much in your case, where the shapes generating the bands are not very sparse vertically.
I'll try playing with the file dimensions too, but so far this is what I got. Note that my svg consists of black shapes on a white background (hence the 255 - x in the following code)
Since the appearance of the bands is extremely random, and processing the same file several times in a row produces different results, I decided to take advantage of randomness: what I do is I export the same svg a few times into different pngs, import them all into a list and then only take those pixels that are white in all the exported images, something like:
images_files = [my_convert_function(svgfile=file, index=i) for i in range(3)]
images = [255 - imageio.imread(x) for x in images_files]
result = reduce(lambda a,b: a & b, images)
imageio.imwrite(<your filename here>, result)
[os.remove(x) for x in images_files]
where my_convert_function contains your same svg2rlg and renderPM.drawToFile, and returns the name of the png file being written. The index 'i' is to save several copies of the same png with different names.
It's some very crude code but I hope it can help other people with the same issue
The format parameter has to be in uppercase
renderPM.drawToFile(drawing, "file.png", fmt="PNG")

Lower the brightness of all RGB pixels by 20% in Python?

I have been trying to teach myself more advanced methods in Python but can't seem to find anything similar to this problem to base my code off of.
First question: Is this only way to display an image in the terminal to install Pillow? I would prefer not to, as I'm trying to then teach what I learn to a very beginner student. My image.show() function doesn't do anything.
Second question: What is the best way to go about lowering the brightness of all RGB pixels in an image by 20%? What I have below doesn't do anything to the alter the brightness, but it also can compile completely. I would prefer the most simple way to go about this as far as importing minimal libraries.
Third Question: How do I made a new picture instead of changing the original? (IE- lower brightness 20%, "image-decreasedBrightness.jpg" is created from "image.jpg")
here is my code - sorry it isn't formatted correctly. Every time i tried to indent it would tab down to the tags bar.
import Image
import ImageEnhance
fileToBeOpened = raw_input("What is the file name? Include file type.")
image = Image.open(fileToBeOpened)
def decreaseBrightness(image):
image.show()
image = image.convert('L')
brightness = ImageEnhance.Brightness(image)
image = brightness.enhance(20)
image.show()
return image
decreaseBrightness(image)
To save the image as a file, there's an example on the documentation:
from PIL import ImageFile
fp = open("lena.pgm", "rb")
p = ImageFile.Parser()
while 1:
s = fp.read(1024)
if not s:
break
p.feed(s)
im = p.close()
im.save("copy.jpg")
The key function is im.save.
For a more in-depth solution, get a nice beverage, find a comfortable place to sit and enjoy your read:
Pillow 3.4.x Documentation.

How do I convert an RGB picture into graysacle using simplecv?

So working with windows, python 2.7 and simplecv I am making a live video with my webcam and want simplecv to give me a grayscale version of the video. Is there any simple way to achieve that?
I found the command
grayscale()
on the opencv page, which should do exactly that but when I run it I get the error:
NameError: name "grayscale" is not defined
I am currently using this prewritten code for object tracking but I don't know whether I should use the command I found, and where in the code I should put it, does anybody have an idea? :
print __doc__
import SimpleCV
display = SimpleCV.Display()
cam = SimpleCV.Camera()
normaldisplay = True
while display.isNotDone():
if display.mouseRight:
normaldisplay = not(normaldisplay)
print "Display Mode:", "Normal" if normaldisplay else "Segmented"
img = cam.getImage().flipHorizontal()
dist = img.colorDistance(SimpleCV.Color.BLACK).dilate(2)
segmented = dist.stretch(200,255)
blobs = segmented.findBlobs()
if blobs:
circles = blobs.filter([b.isCircle(0.2) for b in blobs])
if circles:
img.drawCircle((circles[-1].x, circles[-1].y), circles[-1].radius(),SimpleCV.Color.BLUE,3)
if normaldisplay:
img.show()
else:
segmented.show()
There are multiple ways to do this in SimpleCV.
One way has been already described, it's the toGray() method.
There's also a way you can do this with gaussian blur, which also helps to remove image noise:
from SimpleCV import *
img = Image("simplecv")
img.applyGaussianFilter(grayscale=True)
After the third line, img object contains the image with a lot less high-frequency noise, and converted to grayscale.
You may check out pyimagesearch.com who works with OpenCV, but he explains why applying Gaussian Blur is a good idea.
In simple cv theres a function called toGray() for example:
import SimpleCV as sv
img = img.jpg
sv.img.jpg.toGray()
return gimg.jpg

Categories