I want to calculate the difference betwwn two images. I'm only interested in the difference value for a certain portion of image. For that i am copying the required portion of image to a temp images, and operating on those images. However using the pixel allocation using as specified on http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_core/py_basic_ops/py_basic_ops.html. Here it is given,
ball = img[280:340, 330:390]
img[273:333, 100:160] = ball
Using the similar logic, i have written a python program,
import cv2
import numpy as np
img_file = 'carparking2_1.jpg'
img = cv2.imread(img_file, cv2.IMREAD_COLOR)
img_withoutcar = 'carparking2_1.jpg'
img_withcar = 'carparking2.jpg'
img1 = img_withoutcar[47:151, 106:157]
img2 = img_withcar[47:151, 106:157]
diff1 = cv2.absdiff(img1, img2)
diff2 = cv2.absdiff(img1, img1)
print 'RGB shape: ', img.shape # Rows, cols, channels
print 'Difference with car and without: ', diff1
print 'Difference with car and with car: ', diff2
However, im getting the output message:
File "D:/Projects/IoT Smart Parking/differenceinframes.py", line 8, in <module>
img1 = img_withoutcar[47:151, 106:157]
TypeError: string indices must be integers, not tuple
I am running Python 2.7 with OpenCV 3.1.0 on Windows 10.
You are getting the error because your command is trying to slice the string 'carparking2_1.jpg' as if it were the image data.
#First assign the file names:
file_name_without_car='carparking2_1.jpg'
file_name_with_car='carparking2.jpg'
#load the images
img_withoutcar= cv2.imread(file_name_without_car, cv2.IMREAD_COLOR)
img_withcar= cv2.imread(file_name_with_car, cv2.IMREAD_COLOR)
#now you can slice regions of the images
#note that color images have a third dimension for color channel.
img1 = img_withoutcar[47:151, 106:157,:]
img2 = img_withcar[47:151, 106:157,:]
Related
I have the following two images. One is the original, and the other is the mask. I am attempting to use inpainting to REMOVE everything but the drawn writing on the page.
Image
Mask
I am using the following code to do this:
import cv2
from skimage.restoration import inpaint
image_orig = cv2.imread('R.jpg')
# Create mask with six block defect regions
mask = cv2.imread('InkedR.jpg')
image_result = inpaint.inpaint_biharmonic(image_orig, mask, channel_axis=-1)
I am returned the following error:
ValueError: Input arrays have to be the same shape
I have confirmed that both the image and the mask are the same shape by using:
image_orig. shape == mask.shape
and do not know what is causing this error.
I have tried to use different images, and also convert the images to black and white with no help.
You need to provide the function with a binary mask which can be achieved by extracting the mask from the provided images and then converting it to the binary scale.
Solution:
import cv2
import numpy as np
from skimage.restoration import inpaint_biharmonic
# Load Images
Original_Image = cv2.imread("2.png")
Color_Mask = cv2.imread("1.jpg")
# Subtract Mask
Sub_Mask = np.array(Color_Mask.astype(float)-Original_Image.astype(float))
Sub_Mask = np.float32(Sub_Mask/255).astype('uint8')
# Binary Mask
Mask = cv2.cvtColor(Sub_Mask, cv2.COLOR_BGR2GRAY)
# Apply Inpaint Biharmonic Function
Restored_Image = inpaint_biharmonic(Original_Image, Mask, channel_axis=-1)
# Display Images
cv2.imshow("Display - Mask", Mask)
cv2.imshow("Display - Restored Image", Restored_Image)
cv2.waitKey(0)
Output:
Mask Restored Image
import numpy as np
import cv2
from skimage.io import imread_collection
dataset = r'C:\Users\JasonPC\Documents\CodeVault\Python\FaceRecognition\dataset\*.jpg' # path for images
List = imread_collection(dataset)
faces_list = np.array(List)
def classifier_trainer(faces_list):
img_id = 0
faces = []
faceID = []
for face in np.nditer(faces_list):
gray_face = cv2.cvtColor(face, cv2.COLOR_BGR2GRAY) # coverting color image to gray scale
np_face = np.array(gray_face, 'uint8') # converting gray image into numpy array
img_id += 1
faces.append(np_face)
faceID.append(img_id)
faceID = np.array(faceID)
classifier = cv2.face.LBPHFaceRecognizer_create()
classifier.train(faces, faceID)
classifier.write('Classifier.yml')
classifier_trainer(faces_list)
I'm trying to train a classifier to recognize my face. I'm stuck with this really huge error.
Traceback (most recent call last):
File "c:/Users/JasonPC/Documents/CodeVault/Python/FaceRecognition/trainer.py", line 26, in <module>
classifier_trainer(faces_list)
File "c:/Users/JasonPC/Documents/CodeVault/Python/FaceRecognition/trainer.py", line 15, in classifier_trainer
gray_face = cv2.cvtColor(face, cv2.COLOR_BGR2GRAY) #
coverting color image to gray scale
cv2.error: OpenCV(4.2.0) c:\projects\opencv-python\opencv\modules\imgproc\src\color.simd_helpers.hpp:92: error: (-2:Unspecified error) in function '__thiscall cv::impl::`anonymous-namespace'::CvtHelper<struct cv::impl::`anonymous namespace'::Set<3,4,-1>,struct cv::impl::A0xe227985e::Set<1,-1,-1>,struct cv::impl::A0xe227985e::Set<0,2,5>,2>::CvtHelper(const class cv::_InputArray &,const class cv::_OutputArray &,int)'
> Invalid number of channels in input image:
> 'VScn::contains(scn)'
> where
> 'scn' is 1
All I want my code to do is seek the images from the numpy array i.e face_list and convert it to grayscale and append it to a list called faces
The problem is in how you're iterating over your images. You're using nditer and in your case as it turns out it flattens the n dimensional array to say 1 dimensional and then iterates over all of it's elements. Think of it as a way of iterating over all elements of an n dimensional array without n nested loops. So here, the face variable in your loop is an integer, float or whatever numerical value and you're passing it to cvtColor and getting this error message.
If you want to iterate over the images I think, you can just iterate over them like this:
for face in faces_list:
# your code goes here
I have recorded some data as npy file. And I tried to diplay the image (data[0]) to check if it makes sense with the following code
import numpy as np
import cv2
train_data = np.load('c:/data/train_data.npy')
for data in train_data:
output = data[1]
# only take the height, width and channels of the 4 dimensional array
image = data[0][0, :, :, :]
# image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
cv2.imshow('test', image)
print('output {}'.format(output))
if cv2.waitKey(25) & 0xFF == ord('q'):
cv2.destroyAllWindows()
break
But if I display the images without the line image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) the images seem to be BGR based. If I comment this line into the code the images are displayed correctly.
My question: Does this observation imply that the image array is already in BGR format? Or does this imply that cv2.imshow() does by
default interprete the array as BGR array?
Matplotlib and Numpy read images into RGB and processes them as RGB. OpenCV reads images into BGR and processes them as BGR. Either system recognizes a range of input types, has ways to convert between color spaces of almost any type, and offers support of a variety of image processing tasks.
This gives three different ways to load an image (plt.imread(), ndimage.imread() and cv2.imread()), two systems for processing the data (Numpy and CV2), and two ways to display the image (plt.imshow() and cv2.imshow()), and really, there is a third way to display the image using pyplot, if you want to treat the image as numerical data in 2-d plus another dimension for each color.
Here is some simple code to demonstrate some of this.
#!/usr/bin/python
import matplotlib.pyplot as plt
from scipy.ndimage import imread
import numpy as np
import cv2
img = imread('index.jpg')
print( "img data type: %s shape %s"%( type(img), str( img.shape) ) )
plt.imshow( img )
plt.title( 'pyplot as read' )
plt.savefig( 'index.plt.raw.jpg' )
cv2.imshow('cv2, read by numpy', img)
cv2.imwrite('index.cv2.raw.jpg',img)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
cv2.imshow('after conversion', img)
cv2.imwrite('index.cv2.bgr2rgb.jpg',img)
This generates the following line of text, and the following three example image files.
img data type: <type 'numpy.ndarray'> shape (225, 225, 3)
The correct image has red as the upper circle. We read the image into a numpy array, using ndimage.imread(), and show it with Pyplot's imshow() and get the correct image. We then show it with cv2.imshow() and we see that the red channel is interpreted as the blue channel and vice versa. Then we convert the colorspace and we see that cv2.imshow() now interprets the result correctly.
plt.imshow(), as read by ndimage():
cv2.imshow(), the image as read by ndimage:
cv2.imshow(), after converting from RGB to BGR:
So basically I'm trying to convert a set of RGB images to grayscale using cv2.cvtColor and python is throwing the following error:
Traceback (most recent call last):
File "MCG.py", line 53, in
gray = cv2.cvtColor(data, cv2.COLOR_BGR2GRAY)
TypeError: src is not a numpy array, neither a scalar.
This here is the code:
import numpy as np
import cv2
import dlib
import sys
import skimage
from PIL import Image
import os
import glob
folderpath = sys.argv[1]
cascPath = sys.argv[2]
imageformat = ".tif"
path = folderpath
imfilelist = [os.path.join(path,f) for f in os.listdir(path) if f.endswith(imageformat)]
data = []
for IMG in imfilelist:
print IMG
image = cv2.imread(IMG)
data.append(image)
cv2.imshow('Image', image)
cv2.waitKey(0)
faceCascade = cv2.CascadeClassifier(cascPath)
predictor = dlib.shape_predictor(PREDICTOR_PATH)
gray = cv2.cvtColor(data, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(
gray,
scaleFactor=1.05,
minNeighbors=5,
minSize=(100,100)
)
As you can see, I'm trying to append all these images to a list, which will then be converted using the cv2.cvtColor function. However, that error is thrown. What am I doing wrong? Thank you.
P.S if anyone is wondering why I imported modules that don't seem to be used in this code, this code is just a segment of the whole thing and all of those modules have are being utilized in one way or the other.
If you read the cv2.cvtColor documentation, you can see that the first parameter is the Src 8-bit single channel image. However, in your case you are giving an entire list of images.
So change the code as
gray = []
for j in range(0,len(data)):
gray.append(cv2.cvtColor(np.array(data[j]), cv2.COLOR_BGR2GRAY))
I guess this should work.
You are collecting the images into a list with
data = []
for IMG in imfilelist:
...
data.append(image)
....
and then trying to convert the list with
gray = cv2.cvtColor(data, cv2.COLOR_BGR2GRAY)
This is why you are getting the error - the error is telling you that data is not an image (numpy array) but is a list. You need to convert one image at a time with cv2.cvtColor().
You could try
gray = []
for img in data:
gray.append(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY))
This would give you a list of greyscaled images, which is what I think you want to do.
I read the images using imread and then I would like to compute the average image. How can I add(and divide) using matplotlib?
I'm searching for something like imadd in matlab.
Code:
img1 = matplotlib.image.imread("path")
img2 = matplotlib.image.imread("path1")
img3 = matplotlib.image.imread("path2")
Thanks
You can use the normal sum operations:
img4 = img1 + img2 + img3
This, however, is not exactly the same as imadd from matlab. Matplotlib works with RGB values from 0 to 1. As so the sum in some pixels will provide values superior to 1 (which for the array type is valid; the same would not be true if the data type were uint8). As so perform the following operation to guarantee that your data comes out correct:
img1 = matplotlib.image.imread("path1")
img2 = matplotlib.image.imread("path2")
img3 = np.clip(img1 + img2, 0, 1)
Notice that all images must have the same size.
matplotlib.image is probably what you are looking for. You'll also need numpy if you want to manipulate the images otherwise, because they are basically just arrays in the size of the image (e.g. 1920 x 1080) with 3 or 4 dimensions (RGB or RGBA).
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
img1 = mpimg.imread("foo.png")
img2 = mpimg.imread("bar.png")
Now you are setup for image manipulation. In the case that your images are both in the same format and size (e.g. RGB. Check by using img1.shape and img2.shape) you can do:
img3 = plt.imshow((img1 + img2) / 2)