shreya sharma
shreya sharma

Reputation: 31

Find orientation of object using PCA

image 1

image 2

I want to find the orientation of the bright object in the images attached. For this purpose, I used Principal Component Analysis(PCA).

In case of image 1, PCA finds correct orientation as the first principal component is alligned in that direction. However, in case of image 2, the principal components are disoriented.

Can anyone please explain why the PCA is showing different results in the two images? Also, please suggest if there is some other method to find the orientation of the object.

import os
import gdal
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import skimage
from skimage.filters import threshold_otsu
from skimage.filters import try_all_threshold
import cv2
import math
from skimage import img_as_ubyte
from skimage.morphology import convex_hull_image
import pandas as pd  

file="path to image file"

(fileRoot, fileExt)= os.path.splitext(file)

ds = gdal.Open(file)
band = ds.GetRasterBand(1)
arr = band.ReadAsArray()
geotransform = ds.GetGeoTransform()   
[cols, rows] = arr.shape
thresh = threshold_otsu(arr)
binary = arr > thresh
points = binary>0
y,x = np.nonzero(points) 
x = x - np.mean(x)
y = y - np.mean(y)
coords = np.vstack([x, y])
cov = np.cov(coords)
evals, evecs = np.linalg.eig(cov)
sort_indices = np.argsort(evals)[::-1]
evec1, evec2 = evecs[:, sort_indices]
x_v1, y_v1 = evec1  
x_v2, y_v2 = evec2
scale = 40
plt.plot([x_v1*-scale*2, x_v1*scale*2],
         [y_v1*-scale*2, y_v1*scale*2], color='red')
plt.plot([x_v2*-scale, x_v2*scale],
         [y_v2*-scale, y_v2*scale], color='blue')
plt.plot(x,y, 'k.')
plt.axis('equal')
plt.gca().invert_yaxis()  
plt.show()
theta = np.tanh((x_v1)/(y_v1))  * 180 /(math.pi)

Upvotes: 0

Views: 2074

Answers (1)

Spektre
Spektre

Reputation: 51873

You claim you are using just white pixels. Did you check which ones are selected by some overlay render? Anyway I do not think it is enough especially for your second image as it does not contain any fully saturated white pixels. I would use more processing before the PCA.

  1. enhance dynamic range

    your current images does not need this step as they contain both black and almost fully saturated white. This step allow to unify threshold values among more sample input images. For more info see:

  2. smooth a bit

    this step will significantly lover the intensity of noise points and smooth the edges of bigger objects (but shrink them a bit). This can be done by any FIR filter or convolution or Gaussian filtering. Some also use morphology operators for this.

  3. threshold by intensity

    this will remove darker pixels (clear to black) so noise is fully removed

  4. enlarge remaining objects by morphology operators back to former size

    You can avoid this by enlarging the resulting OBB by few pixels (number is bound to smooth strength from #2).

  5. now apply OBB search

    You are using PCA so use it. I am using this instead:

When I tried your images with above approach (without the #4) I got these results:

results

Another problem I noticed with your second image is that there are not many white pixels in it. That may bias the PCA significantly especially without preprocessing. I would try to enlarge the image by bicubic filtering and use that as input. May be that is the only problem you got with it.

Upvotes: 1

Related Questions