adding an overlay on a DICOM image using open CV - python

I am trying to create a layer on a DICOM image, below code works fine for jpg/png images but not for DICOM.
import cv2
import numpy as np
import pydicom as dicom
ds=dicom.dcmread('D0009.dcm')
img=ds.pixel_array
blank = np.zeros(shape=(img.shape[0],img.shape[1],3), dtype=np.uint8)
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(blank,
text='Logo',
org=(img.shape[1]//8, img.shape[0]//2),
fontFace=font,
fontScale= 2,color=(163,163,163),
thickness=11,
lineType=cv2.LINE_4)
blend=cv2.addWeighted(img,0.7,blank,1, 0, dtype = cv2.CV_32F)
cv2.imshow('sample image dicom',blend)
cv2.waitKey()
any help would be apreciated

I was able to get this working by normalizing the value range of the DICOM image and converting the DICOM image from greyscale to RGB image. Replace your line
img=ds.pixel_array
with these lines:
img = np.array(ds.pixel_array, dtype='float32')
img /= np.max(img)
img = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB)

Related

Converting Color Images to Grayscale but shape of the image stays identical

I've converted some images from RGB to Grayscale for ML purpose.
However the shape of the converted grayscale image is still 3, the same as the color image.
The code for the Conversion:
from PIL import Image
img = Image.open('path/to/color/image')
imgGray = img.convert('L')
imgGray.save('path/to/grayscale/image')
The code to check the shape of the images:
import cv2
im_color = cv2.imread('path/to/color/image')
print(im_color.shape)
im_gray2 = cv2.imread('path/to/grayscale/image')
print(im_gray2.shape)
You did
im_gray2 = cv2.imread('path/to/grayscale/image')
OpenCV does not inspect colorness of image - it does assume image is color and desired output is BGR 8-bit format. You need to inform OpenCV you want output to be grayscale (2D intensity array) as follows
im_gray2 = cv2.imread('path/to/grayscale/image', cv2.IMREAD_GRAYSCALE)
If you want to know more about reading images read OpenCV: Getting Started with Images
cv.imread, without any flags, will always convert any image content to BGR, 8 bits per channel.
If you want any image file, grayscale or color, to be read as grayscale, you can pass the cv.IMREAD_GRAYSCALE flag.
If you want to read the file as it really is, then you need to use cv.IMREAD_UNCHANGED.
im_color = cv2.imread('path/to/color/image', cv2.IMREAD_UNCHANGED)
print(im_color.shape)
im_gray2 = cv2.imread('path/to/grayscale/image', cv2.IMREAD_UNCHANGED)
print(im_gray2.shape)

How to reshape png image read by skimage.imread

Then I read some jpg file, this way
image = imread('aa.jpg')
As result I get dataframe with numbers from 1 to 255
I can resize it this way:
from cv2 import resize
image = resize(image, (256, 256)
But then I doing same think with png, result not desired.
image = imread('aa2.png') # array with number within 0-1 range
resize(image, (256,256)) # returns 1 channel image
resize(image, (256,256, 3)) # returns 3 channel image
Weird image
But imshow(image)
cv2.imread reads the image in 3 channel by default instead of 4. Pass the parameter cv.IMREAD_UNCHANGED to read your PNG file and then try to resize it as shown in the code below.
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
img = cv.imread('Snip20190412_12.png', cv.IMREAD_UNCHANGED)
print(img.shape) #(215, 215, 4)
height, width = img.shape[:2]
res = cv.resize(img,(2*width, 2*height))
print(res.shape)#(430, 430, 4)
plt.imshow(res)
I guess is some problem with your image or code.
Here a free image to try: https://pixabay.com/vectors/copyright-free-creative-commons-98566/
Maybe you have problem with libpng, check this answers: libpng warning: iCCP: known incorrect sRGB profile
Check this simple code that works on PNG images.
import cv2 as cv
image = cv.imread("foto.png")
if __name__ == "__main__":
while True:
image = cv.resize(image,(200,200))
cv.imshow("prueba",image)
key = cv.waitKey(10)
if key == 27:
cv.destroyAllWindows()
break
cv.destroyAllWindows()

im7 image files to openCV

Able to show the image through matplotlib, however unable to do it through cv2.imshow. The shape of the image is not consistent with opencv required formats. Require help on changing on changing it so it can be shown by the command cv2.imshow
test.jpg is a random jpg file from web
import numpy as np
import cv2
import matplotlib.pyplot as plt
import ReadIM
img = cv2.imread('test.jpg')
vbuff, vatts = ReadIM.extra.get_Buffer_andAttributeList('test.im7')
v_array, vbuff = ReadIM.extra.buffer_as_array(vbuff)
print (np.shape(v_array))
print (v_array[0])
print (np.shape(img))
# Showing image through matplotlib
plt.imshow(v_array[0])
plt.show()
#Showing image through cv2
cv2.imshow('image',v_array[0])
cv2.waitKey(0)
cv2.destroyAllWindows()
# Remove memory
#del(vbuff)
ReadIM.DestroyBuffer(vbuff)
ReadIM.DestroyAttributeListSafe(vatts)
test.im7
Normalizing the image to (0,255) will do the trick
img = cv2.normalize(img, None, 255,0,cv2.NORM_MINMAX,dtype = cv2.CV_8UC1)
cv2.imshow('image',img)

Image loaded wrong by opencv

Disaster!
As you can see, the image isn't quite loaded correctly. The original:
The code:
import cv2
import imutils
a=imutils.url_to_image("https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png", readFlag=-1)
cv2.imshow("goog", a)
cv2.waitKey()
The implementation of url_to_image in imutils:
def url_to_image(url, readFlag=cv2.IMREAD_COLOR):
# download the image, convert it to a NumPy array, and then read
# it into OpenCV format
resp = urlopen(url)
image = np.asarray(bytearray(resp.read()), dtype="uint8")
image = cv2.imdecode(image, readFlag)
# return the image
return image
I also tried readFlag=cv2.IMREAD_UNCHANGED, but that didn't do the trick either.
please send help
alright gang we did it
so I tried another version of displaying:
plt.figure("Correct")
plt.imshow(imutils.opencv2matplotlib(a))
plt.show()
No luck it would appear. But then, looking into the opencv2matplotlib source, we find:
def opencv2matplotlib(image):
# OpenCV represents images in BGR order; however, Matplotlib
# expects the image in RGB order, so simply convert from BGR
# to RGB and return
return cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
Aha, but we have 4 channel color (alpha), so by common sense we need cv2.COLOR_BGRA2RGBA not cv2.COLOR_BGR2RGB!!
Testing this theory:
plt.figure("Correct")
plt.imshow(cv2.cvtColor(a, cv2.COLOR_BGRA2RGBA))
plt.show()
We get...
Whoop dee doop!
# import the necessary packages
import numpy as np
import urllib
import cv2
def url_to_image(url):
# download the image, convert it to a NumPy array, and then read
# it into OpenCV format
resp = urllib.request.urlopen(url)
image = np.asarray(bytearray(resp.read()), dtype="uint8")
image = cv2.imdecode(image, cv2.IMREAD_COLOR)
# return the image
return image
# initialize the list of image URLs to download
url="http://i.dailymail.co.uk/i/pix/2015/09/01/18/2BE1E88B00000578-3218613-image-m-5_1441127035222.jpg"
print ("downloading %s" % (url))
image = url_to_image(url)
cv2.imshow("Image", image)
cv2.waitKey(0)
And the output is:

How can i read input only a part of the image without creating another image?

import cv2
fname = '1.png'
img=cv2.imread(fname, 0)
print (img)//the outcome is an array of values from 0 to 255 (grayscale)
ret, thresh = cv2.threshold(img, 254, 255, cv2.THRESH_BINARY)
thresh = cv2.bitwise_not(thresh)
nums, labels = cv2.connectedComponents(thresh, None, 4, cv2.CV_32S)
dst = cv2.convertScaleAbs(255.0*labels/nums)
cv2.imwrite(dest_dir+"output.png", dst)
that code works just fine, so i moved on to adjusting my code so it can take a portion of the image not the entire image:
from PIL import Image
img = Image.open(fname)
img2 = img.crop((int(xmin), int(yMin),int(xMax), int(yMax))
xmin ymin xmax ymax simply being the top left bottom right coordinates of the box.
then i did img = cv2.imread(img2) to continue as the previous code but got an error, i printed img2 and got <PIL.Image.Image image mode=RGB size=54x10 at 0x7F4D283AFB70> how can i adjust it to be able to input that crop or image portion instead of fname in my code above, and kindly note i don't want to save img2 as an image and carry on from there because i need to work on the main image.
try cv2.imshow() instead of printing it. In order to see an image you cropped, you need to use cv2 function. here is a sample code:
import numpy as np
import cv2
# Load an color image in grayscale
img = cv2.imread('messi5.jpg',0)
cv2.imshow('image',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
The simple answer is NO you cannot.
Open up your terminal /IDE and type in help(cv2.imread).
It clearly states that The function imread loads an image from the specified file and returns it. So in order to use cv2.imread() you must pass it in as a file not an image.
Your best bet would be to save your cropped image as a file and then read it.

Categories