how to find the pca of an image using python and opencv? - python

I am developing an image classifier using svm.In the feature extraction phase can i use pca as feature.How to find the pca of an image using python and opencv.what my plan is
Find pca of each image in training set and store it in a array.It may be list of lists
Store class labels in another list
pass this as argument to svm
Am i going in right Direction.Please help me

Yes you can do PCA+SVM, some might argue that PCA is not the best feature to use or SVM is not the best classification algorithm. But hey, have a good start is better than sitting around.
To do PCA with OpenCV, try something like (I haven't verified the codes, just to get you an idea):
import os
import cv2
import numpy as np
# Construct the input matrix
in_matrix = None
for f in os.listdir('dirpath'):
# Read the image in as a gray level image. Some modifications
# of the codes are needed if you want to read it in as a color
# image. For simplicity, let's use gray level images for now.
im = cv2.imread(os.path.join('dirpath', f), cv2.IMREAD_GRAYSCALE)
# Assume your images are all the same size, width w, and height h.
# If not, let's resize them to w * h first with cv2.resize(..)
vec = im.reshape(w * h)
# stack them up to form the matrix
try:
in_matrix = np.vstack((in_matrix, vec))
except:
in_matrix = vec
# PCA
if in_matrix is not None:
mean, eigenvectors = cv2.PCACompute(in_matrix, np.mean(in_matrix, axis=0).reshape(1,-1))

Related

object segmentation using mean shift

i have this image:
I am interested to do segmentation only in the objects that appear in the image so i did something like this
import numpy as np
import cv2
from sklearn.cluster import MeanShift, estimate_bandwidth
#from skimage.color import rgb2lab
#Loading original image
originImg = cv2.imread('test/2019_00254.jpg')
# Shape of original image
originShape = originImg.shape
# Converting image into array of dimension [nb of pixels in originImage, 3]
# based on r g b intensities
flatImg=np.reshape(originImg, [-1, 3])
# Estimate bandwidth for meanshift algorithm
bandwidth = estimate_bandwidth(flatImg, quantile=0.1, n_samples=100)
ms = MeanShift(bandwidth = bandwidth, bin_seeding=True)
# Performing meanshift on flatImg
ms.fit(flatImg)
# (r,g,b) vectors corresponding to the different clusters after meanshift
labels=ms.labels_
# Remaining colors after meanshift
cluster_centers = ms.cluster_centers_
# Finding and diplaying the number of clusters
labels_unique = np.unique(labels)
n_clusters_ = len(labels_unique)
print("number of estimated clusters : %d" % n_clusters_)
segmentedImg = cluster_centers[np.reshape(labels, originShape[:2])]
cv2.imshow('Image',segmentedImg.astype(np.uint8))
cv2.waitKey(0)
cv2.destroyAllWindows()
but the problem is its doing segmentation in the whole image including the background so how can i do segmentation on the objects only note that i have bboxes coordinates of each object
I'd suggest you use a more straightforward input to understand (and feel) all the limitations behind the approach. The input you have is complex in terms of resolution, colors, scene complexity, object complexity, etc.
Anyway, to make this answer useful, let's do some experiments:
Detectron2, PointRend segmentation
Just in case you expect a complex model to handle the scene properly. Segmentation:
Masks:
No miracle here. The scene and objects are complex.
Monocular depth estimation
Let's try depth estimation as an obvious way to get rid of the background.
Depth (also check this example):
Result:
Part of the background is gone, but nothing to do with other objects.
Long story short, start with something simple to see the exact way your solution works.
BTW, it is always hard to work with thin and delicate details, so it is better to avoid that complexity if possible.

Using perspective transformation to change point of view of an image. Not getting desired result

I am trying to change the perspective of the first image according to the second image. For finding the homography matrix I have found the four coordinates of a common object(white notice board) in both images.
Image 1
Image 2
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
img1 = cv2.imread("rgb per.jpg")
img2 = cv2.imread("IR per.jpg")
img_1_coor = np.float32([[1178,425], [1201,425], [1178,439], [1201,439], [1551,778]]) #coordinate of white notice board in rgb image
img_2_coor = np.float32([[370,98], [381,103], [367,107], [380,112], [498,332]]) #coordinate of same object in IR image
for x in range(0,4):
cv2.circle(img1,(img_1_coor[x][0],img_1_coor[x][1]),5,(255,0,0),1)
matplotlib.rcParams['figure.dpi'] = 300
#plt.imshow(img1) #this verified that the found coordinates are correct
#P = cv2.getPerspectiveTransform(img_1_coor,img_2_coor)
H, s = cv2.findHomography (img_1_coor,img_2_coor)
print(s)
perspective = cv2.warpPerspective(img1, H, img2.shape[:2])
plt.imshow(perspective)
#the resulting image
Output image
I want the output to be like image 1 with point-of-view(camera angle) as image 2. If this is not possible, vice versa would also be helpful to have image 2 with the point of view as image 1.
Can someone tell if it's possible to use coordinates of the object in image to change the perspective of full-image, if yes is there any problem with my code?
I recommend a computer vision package that implements the perspective transform (e.g. OpenCV or whatever they use nowadays). It is a fairly common computer vision operation. It is also known less properly as corner-pinning.
If you wish to implement it yourself as an exercise, you may look at the Direct Linear Transform where you solve your matrix problem in homogenous coordinates, possibly by using a singular value decomposition.

What is the difference between opencv ximgproc.slic and skimage segmentation.slic?

I run the SLIC (Simple Linear Iterative Clustering) superpixels algorithm from opencv and skimage on the same picture with, but got different results, the skimage slic result is better, Shown in the picture below.First one is opencv SLIC, the second one is skimage SLIC. I got several questions hope someonc can help.
Why opencv have the parameter 'region_size' while skimage is 'n_segments'?
Is convert to LAB and a guassian blur necessary?
Is there any trick to optimize the opecv SLIC result?
===================================
OpenCV SLIC
Skimage SLIC
# Opencv
src = cv2.imread('pic.jpg') #read image
# gaussian blur
src = cv2.GaussianBlur(src,(5,5),0)
# Convert to LAB
src_lab = cv.cvtColor(src,cv.COLOR_BGR2LAB) # convert to LAB
# SLIC
cv_slic = ximg.createSuperpixelSLIC(src_lab,algorithm = ximg.SLICO,
region_size = 32)
cv_slic.iterate()
# Skimage
src = io.imread('pic.jpg')
sk_slic = skimage.segmentation.slic(src,n_segments = 256, sigma = 5)
Image with superpixels centroid generated with the code below
# Measure properties of labeled image regions
regions = regionprops(labels)
# Scatter centroid of each superpixel
plt.scatter([x.centroid[1] for x in regions], [y.centroid[0] for y in regions],c = 'red')
but there is one superpixel less(top-left corner), and I found that
len(regions) is 64 while len(np.unique(labels)) is 65 , why?
I'm not sure why you think skimage slic is better (and I maintain skimage! 😂), but:
different parameterizations are common in mathematics and computer science. Whether you use region size or number of segments, you should get the same result. I expect the formula to convert between the two will be something like n_segments = image.size / region_size.
The original paper suggests that for natural images (meaning images of the real world like you showed, rather than e.g. images from a microscope or from astronomy), converting to Lab gives better results.
to me, based on your results, it looks like the gaussian blur used for scikit-image was higher than for openCV. So you could make the results more similar by playing with the sigma. I also think the compactness parameter is probably not identical between the two.

Getting and comparing BOVW histograms for image similarity

I'm building an image similarity program and, as I am a begginer in CV, I talked with an expert who gave me the following recommended steps to get the really basic functionality:
Extract keypoints (DoG, Harris, etc.) and local invariant descriptors (SIFT, SURF, etc.) from all images.
Cluster them to form a codebook (bag of visual words dictionary; BOVW)
Quantize the features from each image into a BOVW histogram
Compare the BOVW histograms for each image (typically using chi-squared, cosine, or euclidean distance)
The point number one is easy, but I start getting confused at step 2. This is the code I've written so far:
import cv2
import numpy as np
dictionarySize = 20
BOW = cv2.BOWKMeansTrainer(dictionarySize)
for imgpath in ['testimg/testcropped1.jpg','testimg/testcropped2.jpg','testimg/testcropped3.jpg']:
img = cv2.imread(imgpath)
gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
dst = cv2.cornerHarris(gray,2,3,0.04)
sift = cv2.xfeatures2d.SIFT_create()
kp = sift.detect(gray,None)
kp,des = sift.compute(img,kp)
img=cv2.drawKeypoints(gray,kp,img)
cv2.imwrite('%s_keypoints.jpg' % imgpath, img)
BOW.add(des)
I extract some features using SIFT and then I try to build a BOVW o each image descriptor. The problem is I have no idea if this is correct and how to get the histograms.

Finding Variance of an image in OpenCV -Python

I am trying to find the variance of a greyscale image in OpenCV -Python. I first take the image read in and split it into sub-images, I want to calculate the variance of these sub-images (cropped_img).
I'm not sure how to calculate variance in python, I assumed that I could calculate the covariance matrix to find the variance using the rule:
Var(X) = Cov(X,X)
The thing is I can't get my head around how to use cv2.calcCovarMatrix(), and I can't find any examples in python.
I did find this example in C++ but I have never used the language and im struggling to convert it into python: calcCovarMatrix in multichannel image and unresolved assertion error
Here is my code:
#import packages
import numpy as np
import cv2
#Read in image as grey-scale
img = cv2.imread('images/0021.jpg', 0)
#Set scale of grid
scale = 9
#Get x and y components of image
y_len,x_len = img.shape
covar = []
for y in range(scale):
for x in range(scale):
#Crop image 9*9 windows
cropped_img=img[(y*y_len)/scale:((y+1)*y_len)/scale,
(x*x_len)/scale:((x+1)*x_len)/scale]
#Here is where I need to calc variance
cv2.calcCovarMatrix(cropped_img, covar, meanBGR, cv2.cv.CV_COVAR_NORMAL)
#???
cropped_img[:] = covar
cv2.imshow('output_var',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
If anyone has any ideas or if you have a better way to calculate variance then I would be extremely grateful.
Thanks.
EDIT: I also found this example in c; mean and variance of image in single pass, but it doesn't seem too efficient.
To get the variance of gray scale image in python you can use numpy.
import numpy as np
var = np.var(img)

Categories