Reputation: 31
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
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.
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:
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.
threshold by intensity
this will remove darker pixels (clear to black) so noise is fully removed
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).
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:
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