Can't open an image from URL in opencv - python

I'm working on a program that reads csv file to get the names of colors, compares RGB values with RGB values of an image from URL. I think the program doesn't get image from URL since I tried to imshow() to check whether image is passed into program or not. I get this error
(-215:Assertion failed) size.width>0 && size.height>0 in function 'imshow'
This is the code:
import numpy as np #needed to work with matrix of an image
import pandas as pd #needed to work with color.csv
import cv2 #needed to work with image
import matplotlib.pyplot as pl #needed to work with plotting
import urllib.request#needed to work with image url
#step 1. Read csv file with name, RGB and HEX values.
#step 2. Set color detection function. Get value of pixels in a NumPy array
#step 3. Compare RGB value of a pixel with dataframe.
#step 4. Save the name and RBG value inside a file.
#image from url
def url_to_image(url): #doesn't get file, need to work upon this
resp = urllib.request.urlopen(url)
image = np.asarray(bytearray(resp.read()), dtype='uint8')
image = cv2.imdecode(image,cv2.IMREAD_COLOR)
return image
#dataframe with 864 colors
index = ['color', 'color_name', 'hex','R','G','B']
csv = pd.read_csv('colors.csv', names = index, header = None)
def getColor(R,G,B):
minimum = 10000
for i in range(len(csv)):
distance = abs(R-int(csv.loc[i, 'R'])) + abs(G-int(csv.loc[i, 'G'])) + abs(B-int(csv.loc[i,'B']))
if(distance<=minimum):
minimum = distance
color_name = csv.loc[i, 'color_name']
return color_name
img = url_to_image("https://upload.wikimedia.org/wikipedia/commons/2/24/Solid_purple.svg")
cv2.imshow("image", img)
cv2.waitKey(0)

It doesn't work because you are trying to use an svg Image (which is vector based) to open in an Matrix like an JPEG or PNG image (which are raster based). It doesn't work like that with these.
Try loading a different Image like this
https://miro.medium.com/max/800/1*bNfxs62uJzISTfuPlOzOWQ.png EDIT sry wrong link
https://htmlcolorcodes.com/assets/images/colors/purple-color-solid-background-1920x1080.png
this will work because this is an png
As far as i know Opencv has no good support for SVG based Images

Related

How to retain the colors of a PNG image when converting back from an array

Whenever I convert a PNG image to a np.array and then convert it back to a PNG I lose all the colors of the image. I would like to be able to retain the colors of the original PNG when I am converting it back from a np.array.
Original PNG Image
My code:
from PIL import Image
im = Image.open('2007_000129.png')
im = np.array(im)
#augmenting image
im[0,0] = 1
im = Image.fromarray(im, mode = 'P')
Outputs a black and white version of the image
I also try using getpalette and putpalette but this does not work it just returns a NonType object.
im = Image.open('2007_000129.png')
pat = im.getpalette()
im = np.array(im)
im[0,0] = 1
im = Image.fromarray(im, mode = 'P')
im= im.putpalette(pat)
Your image is using single channel color using palette. Try the code below. Also you can check more about this subject at What is the difference between images in 'P' and 'L' mode in PIL?
from PIL import Image
import numpy as np
im = Image.open('gsmur.png')
rgb = im.convert('RGB')
np_rgb = np.array(rgb)
p = im.convert('P')
np_p = np.array(p)
im = Image.fromarray(np_p, mode = 'P')
im.show()
im2 = Image.fromarray(np_rgb)
im2.show()
Using the second code provided, the error comes from this line:
im= im.putpalette(pat)
If you refer to the documentation of Image.putpalette, you see that this function doesn't return any value, thus Image.putpalette is applied to the corresponding image directly. So, (re-)assigning the non-existent return value (which then is None) is not necessary – or, as seen here, erroneous.
So, the simple fix is just to use:
im.putpalette(pat)
Using this change, the second code provided works as intended.

Using dicom Images with OpenCV in Python

I am trying to use a dicom image and manipulate it using OpenCV in a Python environment. So far I have used the pydicom library to read the dicom(.dcm) image data and using the pixel array attribute to display the picture using OpenCV imshow method. But the output is just a blank window. Here is the snippet of code I am using at this moment.
import numpy as np
import cv2
import pydicom as dicom
ds=dicom.dcmread('sample.dcm')
cv2.imshow('sample image dicom',ds.pixel_array)
cv2.waitkey()
If i print out the array which is used here, the output is different from what i would get with a normal numpy array. I have tried using matplotlib imshow method as well and it was able to display the image with some colour distortions. Is there a way to convert the array into a legible format for OpenCV?
Faced a similar issue. Used exposure.equalize_adapthist() (source). The resulting image isn't a hundred percent to that you would see using a DICOM Viewer but it's the best I was able to get.
import numpy as np
import cv2
import pydicom as dicom
from skimage import exposure
ds=dicom.dcmread('sample.dcm')
dcm_sample=ds.pixel_array
dcm_sample=exposure.equalize_adapthist(dcm_sample)
cv2.imshow('sample image dicom',dcm_sample)
cv2.waitkey()
I have figured out a way to get the image to show. As Dan mentioned in the comments, the value of the matrix was scaled down and due to the imshow function, the output was too dark for the human eye to differentiate. So, in the end the only thing i needed to do was multiply the entire mat data with 128. The image is showing perfectly now. multiplying the matrix by 255 over exposes the picture and causes certain features to blow. Here is the revised code.
import numpy as np
import cv2
import pydicom as dicom
ds=dicom.dcmread('sample.dcm')
dcm_sample=ds.pixel_array*128
cv2.imshow('sample image dicom',dcm_sample)
cv2.waitkey()
I don't think that is a correct answer. It works for that particular image because most of your pixel values are in the lower range. Check this OpenCV: How to visualize a depth image. It is for c++ but easily adapted to Python.
This is the best way(in my opinion) to open image in opencv as a numpy array while perserving the image quality:
import numpy as np
import pydicom, os, cv2
def dicom_to_numpy(ds):
DCM_Img = ds
rows = DCM_Img.get(0x00280010).value #Get number of rows from tag (0028, 0010)
cols = DCM_Img.get(0x00280011).value #Get number of cols from tag (0028, 0011)
Instance_Number = int(DCM_Img.get(0x00200013).value) #Get actual slice instance number from tag (0020, 0013)
Window_Center = int(DCM_Img.get(0x00281050).value) #Get window center from tag (0028, 1050)
Window_Width = int(DCM_Img.get(0x00281051).value) #Get window width from tag (0028, 1051)
Window_Max = int(Window_Center + Window_Width / 2)
Window_Min = int(Window_Center - Window_Width / 2)
if (DCM_Img.get(0x00281052) is None):
Rescale_Intercept = 0
else:
Rescale_Intercept = int(DCM_Img.get(0x00281052).value)
if (DCM_Img.get(0x00281053) is None):
Rescale_Slope = 1
else:
Rescale_Slope = int(DCM_Img.get(0x00281053).value)
New_Img = np.zeros((rows, cols), np.uint8)
Pixels = DCM_Img.pixel_array
for i in range(0, rows):
for j in range(0, cols):
Pix_Val = Pixels[i][j]
Rescale_Pix_Val = Pix_Val * Rescale_Slope + Rescale_Intercept
if (Rescale_Pix_Val > Window_Max): #if intensity is greater than max window
New_Img[i][j] = 255
elif (Rescale_Pix_Val < Window_Min): #if intensity is less than min window
New_Img[i][j] = 0
else:
New_Img[i][j] = int(((Rescale_Pix_Val - Window_Min) / (Window_Max - Window_Min)) * 255) #Normalize the intensities
return New_Img
file_path = "C:/example.dcm"
image = pydicom.read_file(file_path)
image = dicom_to_numpy(image)
#show image
cv2.imshow('sample image dicom',image)
cv2.waitKey(0)
cv2.destroyAllWindows()

TypeError: too many data entries

i am trying to recreate a picture. I take a picture edging it and save it. after i made it grayscale and save it. Found the common pixels of the two images and I am trying to recreate again the picture and i get this error. It is a picture of a road and i am trying to keep only the white lanes. so after i compare the edged picture with the first picture most common pixels are the white ones that represent the lanes of the road.
The error is thrown in line marked <———-- near the end of the code listing
TypeError: too many data entries
newpic is the list in that form `[1,1,1,1,...,1]
here is my code and explaining every part. if you have any other suggestion how to achieve the result i want please say it
#LIBRARIES
import cv2
import numpy as np
import matplotlib as mpl
from matplotlib import pyplot as plt
#read and display the image
img = cv2.imread("road.jpg")
#original picture show
cv2.imshow("Window Name",img)
# edging the image
edges = cv2.Canny(img,255,255)
#show the canny picture
cv2.imshow("Window Name",edges)
#save the canny picture First argument is the file name, second
argument is the image you want to save.
cv2.imwrite('canny.png',edges)
#making the image an array
from PIL import Image
#read the pciture
img = Image.open('road.jpg').convert('LA')
#save it
img.save('greyscale.png')
#open the edited
im=Image.open("greyscale.png")
#make it an array
pix_val = list(im.getdata())
pix_val_flat = [x for sets in pix_val for x in sets]
# pix_val_flat has the pixels for out first image without edging
#print the array
#print (pix_val_flat[125]);
#get the lenght of the array
lenght=len(pix_val_flat)
#print the array
#print(lenght);
#take the canny picture and make it grayscale
edge = Image.open('canny.png').convert('LA')
#make it array
pix_val1 = list(edge.getdata())
pix_val_flat1 = [x for sets in pix_val for x in sets]
#get the lenght of the array
#lenght1=len(pix_val_flat1)
#prnt the array
#print(lenght);
#print the array
#print (pix_val_flat1[125]);
print(lenght)
newpic = [0]*lenght
lenght2=len(newpic)
print (newpic)
for c1 in range(0,lenght,3):
if pix_val_flat[c1]==pix_val_flat1[c1] and
pix_val_flat[c1+1]==pix_val_flat1[c1+1] and
pix_val_flat[c1+2]==pix_val_flat1[c1+2]:
newpic[c1]= pix_val_flat1[c1]
newpic[c1+1]= pix_val_flat1[c1+1]
newpic[c1+2]= pix_val_flat1[c1+2]
array = np.array(newpic, dtype=np.uint8)
print (array)
im2 = Image.new(im.mode, im.size)
im2.putdata (newpic) ---------------------> here i get the error
new_image = Image.fromarray(array)
new_image.save('hello.png')
cv2.waitKey(0)
cv2.destroyAllWindows()
In this case it means that your putting more data than the size you set before.
You can check the length of data you put in with len(the_list_of_data), so you'll see length gets double every time you put data (even if you overwrite). You can set the_list_of_data length to 0 and then fill it with data. This error occurs in loops too.

Create an image using the pixels median fom other images

I have six images and I want to find the median of each pixel and create a new pic from it.
I created a list of my images in this manner:
imgs=['1.jpg', '2.jpg', '3.jpg', '4.jpg', '5.jpg', '6.jpg']
and then I wrote a for loop like that:
for image in imgs:
I've found that there's a function that finds the median using numpy but I don't know how to use it. Also, after finding the median how can I create a picture of all the medians in the correct position of the screen?
How to convert the image into an array?
You can use opencv to read images
import cv2
import numpy as np
imgs=['1.jpg', '2.jpg', '3.jpg', '4.jpg', '5.jpg', '6.jpg']
np_images = []
for img in imgs:
image = cv2.imread(img,1)
if image is None:
print(img, "doesnot exist")
else:
np_images.append(image)
# assuming the dimensions of all images are the same
np_array = np.array(np_images)
median_image = np.median(np_array,axis=0)
cv2.imwrite("median_image.jpg",median_image)
Edit:
np_images is an array to store images read by opencv
p_value is an array to store color value of pixel at (row,col)
np.zeros is a function that produces zero matrix(matrix whose all
values are zeros) of given shape.
To speed up the program.

How to crop bottom part of an image(part with subtitle) in python

I am doing subtitle extraction from videos in python.I have used opencv in python to do this.I have divided it into frames and for each frame as image which will be stored in my disk, i am doing ocr on it.But I dont want to perform ocr on the entire image.I just want the subtitle part.I manually cropped the image with these values 278:360 as my image size was 360:640.But the image size varies for different video files.Now my question is how to crop the subtitle part alone programatically.Please do answer.Thanks in advance
textImage = image[278:360,:]
You can take the last third of the image height, if you are sure that the subtitles will be there.
For instance, for the following image:
Proceed as follows:
read the image into a numpy array :
In my example, I am using imread from skimage.io, but you can use opencv:
from skimage.io import imread
img = imread('http://cdn.wccftech.com/wp-content/uploads/2017/05/subtitle-of-a-blu-ray-movie.jpg')
img.shape # >>> (383, 703, 3)
Get the bottom third of the image (which contains the subtitle):
The idea is to divide the height of the image by 3 and take the bottom third of the image:
crop_position = int(img.shape[0]/3)
subtitle_img = img[img.[0] - crop_position:,:,:]
The resulting subtitle_img looks like this:
In my case I use only one library and regular operations on arrays:
import matplotlib.image as mpimg
image= mpimg.imread('someImage.jpg')
#Example for bottom half of an image, but you can replace this with your parameter
crop_position = image.shape[0] // 2
half_imagage = image[image.shape[0] - crop_position:,:]
And it returns a nice image:

Categories

Resources