تنفيذ كاشف زاوية هاريس
-
27-09-2019 - |
سؤال
أقوم بتنفيذ كاشف زاوية هاريس لأغراض تعليمية ، لكنني عالق في جزء استجابة هاريس. في الأساس ، ما أفعله ، هو:
- حساب تدرجات شدة الصورة في الاتجاه x و y
- إخراج طمس (1)
- حساب استجابة هاريس على إخراج (2)
- قم بقمع غير Maximas في إخراج (3) في إخراج 3 × 3 و 3 × 3
1 و 2 يبدو أنهما يعملان بشكل جيد ؛ ومع ذلك ، أحصل على قيم صغيرة جدًا مثل استجابة Harris ، ولا توجد جدوى تصل إلى العتبة. الإدخال هو التصوير الفوتوغرافي في الهواء الطلق القياسي.
[...]
[Ix, Iy] = intensityGradients(img);
g = fspecial('gaussian');
Ix = imfilter(Ix, g);
Iy = imfilter(Iy, g);
H = harrisResponse(Ix, Iy);
[...]
function K = harrisResponse(Ix, Iy)
max = 0;
[sy, sx] = size(Ix);
K = zeros(sy, sx);
for i = 1:sx,
for j = 1:sy,
H = [Ix(j,i) * Ix(j,i), Ix(j,i) * Iy(j,i)
Ix(j,i) * Iy(j,i), Iy(j,i) * Iy(j,i)];
K(j,i) = det(H) / trace(H);
if K(j,i) > max,
max = K(j,i);
end
end
end
max
end
بالنسبة لصورة العينة ، ينتهي Max إلى 6.4163e-018 والتي تبدو منخفضة للغاية.
المحلول
يتم تعريف زاوية في اكتشاف زاوية هاريس على أنها "أعلى قيمة بكسل في المنطقة" (عادة ما تكون 3X3
أو 5x5
) لذا فإن تعليقك حول عدم وجود جدوى من الوصول إلى "عتبة" يبدو غريباً بالنسبة لي. فقط جمع جميع وحدات البكسل التي لها قيمة أعلى من جميع وحدات البكسل الأخرى في 5x5
حي من حولهم.
بصرف النظر عن ذلك: لست متأكدًا بنسبة 100 ٪ ، لكنني أعتقد أنه يجب أن يكون لديك:
K(j,i) = det(H) - lambda*(trace(H)^2)
عندما يكون Lambda ثابتًا إيجابيًا يعمل في قضيتك (والقيمة المقترحة Harris هي 0.04).
بشكل عام ، تكون اللحظة الوحيدة المعقولة لتصفية مدخلاتك قبل هذه النقطة:
[Ix, Iy] = intensityGradients(img);
الفلتره Ix2
, Iy2
و Ixy
لا معنى له بالنسبة لي.
علاوة على ذلك ، أعتقد أن رمز العينة الخاص بك خاطئ هنا (هل تعمل harrisResponse
لديك اثنين أو ثلاثة متغيرات إدخال؟):
H = harrisResponse(Ix2, Ixy, Iy2);
[...]
function K = harrisResponse(Ix, Iy)
نصائح أخرى
الحل الذي قمت بتطبيقه مع Python ، إنه يعمل بالنسبة لي آمل أن تجد ما تبحث عنه
import numpy as np
import matplotlib.pyplot as plt
from PIL.Image import *
from scipy import ndimage
def imap1(im):
print('testing the picture . . .')
a = Image.getpixel(im, (0, 0))
if type(a) == int:
return im
else:
c, l = im.size
imarr = np.asarray(im)
neim = np.zeros((l, c))
for i in range(l):
for j in range(c):
t = imarr[i, j]
ts = sum(t)/len(t)
neim[i, j] = ts
return neim
def Harris(im):
neim = imap1(im)
imarr = np.asarray(neim, dtype=np.float64)
ix = ndimage.sobel(imarr, 0)
iy = ndimage.sobel(imarr, 1)
ix2 = ix * ix
iy2 = iy * iy
ixy = ix * iy
ix2 = ndimage.gaussian_filter(ix2, sigma=2)
iy2 = ndimage.gaussian_filter(iy2, sigma=2)
ixy = ndimage.gaussian_filter(ixy, sigma=2)
c, l = imarr.shape
result = np.zeros((c, l))
r = np.zeros((c, l))
rmax = 0
for i in range(c):
print('loking for corner . . .')
for j in range(l):
print('test ',j)
m = np.array([[ix2[i, j], ixy[i, j]], [ixy[i, j], iy2[i, j]]], dtype=np.float64)
r[i, j] = np.linalg.det(m) - 0.04 * (np.power(np.trace(m), 2))
if r[i, j] > rmax:
rmax = r[i, j]
for i in range(c - 1):
print(". .")
for j in range(l - 1):
print('loking')
if r[i, j] > 0.01 * rmax and r[i, j] > r[i-1, j-1] and r[i, j] > r[i-1, j+1]\
and r[i, j] > r[i+1, j-1] and r[i, j] > r[i+1, j+1]:
result[i, j] = 1
pc, pr = np.where(result == 1)
plt.plot(pr, pc, 'r+')
plt.savefig('harris_test.png')
plt.imshow(im, 'gray')
plt.show()
# plt.imsave('harris_test.png', im, 'gray')
im = open('chess.png')
Harris(im)
التنفيذ المقترح غير فعال بشكل رهيب. لنبدأ بعد حساب التدرجات (والتي يمكن تحسينها أيضًا):
A = Ix.^2;
B = Iy.^2;
C = (Ix.*Iy).^4;
lambda = 0.04;
H = (A.*B - C) - lambda*(A+B).^2;
% if you really need max:
max(H(:))
لا حلقات مطلوبة ، لأن ماتلاب يكره الحلقات.
في الأساس ، سيكون للكشف عن ركن هاريس 5 خطوات:
- حساب التدرج
- تجانس غاوسي
- هاريس قياس الحساب
- قمع غير أقصى
- عتبة
إذا كنت تنفذ في MATLAB ، فسيكون من السهل فهم الخوارزمية والحصول على النتائج.
قد يساعدك الكود التالي لـ Matlab في حل شكوكك:
% Step 1: Compute derivatives of image
Ix = conv2(im, dx, 'same');
Iy = conv2(im, dy, 'same');
% Step 2: Smooth space image derivatives (gaussian filtering)
Ix2 = conv2(Ix .^ 2, g, 'same');
Iy2 = conv2(Iy .^ 2, g, 'same');
Ixy = conv2(Ix .* Iy, g, 'same');
% Step 3: Harris corner measure
harris = (Ix2 .* Iy2 - Ixy .^ 2) ./ (Ix2 + Iy2);
% Step 4: Find local maxima (non maximum suppression)
mx = ordfilt2(harris, size .^ 2, ones(size));
% Step 5: Thresholding
harris = (harris == mx) & (harris > threshold);
هناك وظيفة لذلك في صندوق أدوات نظام رؤية الكمبيوتر المسمى detectHarrisFeatures
.