나는 개 발 아래 압력을 측정하는 수의과 클리닉을 돕고 있습니다. 저는 데이터 분석을 위해 파이썬을 사용합니다. 이제는 발을 (해부학적인) 하위 영역으로 나누려고 노력했습니다.
각 발에 대한 2D 배열을 만들었습니다.이 배열은 시간에 따라 발에 의해로드 된 각 센서의 최대 값으로 구성됩니다. 다음은 한 발의 예입니다. Excel을 사용하여 '탐지'하려는 영역을 그렸습니다. 이것들은 로컬 맥시마와 함께 센서 주위에 2 x 2 박스이며, 함께 최대 합계를가집니다.
그래서 약간의 실험을 시도하고 각 열과 행의 최대 값을 찾도록 결정했습니다 (발 모양 때문에 한 방향으로 볼 수 없음). 이것은 분리 발가락의 위치를 '감지'하는 것처럼 보이지만 이웃 센서를 표시합니다.
파이썬에게이 최대 값 중 어느 것이 내가 원하는 값인지를 알려주는 가장 좋은 방법은 무엇일까요?
참고 : 2x2 정사각형은 서로 구별되어야하기 때문에 겹칠 수 없습니다!
또한 편의상 2x2를 사용했는데 더 많은 고급 솔루션을 사용할 수는 있지만 간단히 인간 운동 과학자이므로 실제 프로그래머 나 수학자가 아니므로 '단순하게'유지하십시오.
그래서 @ jextee의 솔루션을 시도했습니다 (아래 결과 참조). 보시다시피 앞 발에 매우 효과적이지만 뒷다리에는 잘 작용하지 않습니다.
더 구체적으로, 네 번째 발가락의 작은 피크를 인식 할 수 없습니다. 이것은 분명히 루프가 가장 낮은 값으로 내려가는 것을 고려하지 않고이 값이 가장 아래쪽을 향하는 것처럼 보입니다.
누구든지 @ jextee의 알고리즘을 조정하는 방법을 알고 있으므로 네 번째 발가락도 찾을 수 있을까요?
아직 다른 시험을 진행하지 않았으므로 다른 샘플을 제공 할 수 없습니다. 그러나 전에 내가 준 데이터는 각 발의 평균입니다. 이 파일은 접시와 접촉 한 순서대로 9 발의 최대 데이터를 가진 배열입니다.
이 이미지는 그들이 공간적으로 판 위에 펼쳐진 모습을 보여줍니다.
관심있는 사람을 위해 블로그를 만들었습니다.과모든 원시 측정으로 SkyDrive를 설정했습니다.따라서 더 많은 데이터를 요구하는 모든 사람에게 : 더 많은 힘을!
그래서 도움에 관한 내 질문에 관한발 감지과발 정렬, 마침내 모든 발에 대한 발가락 감지를 확인할 수있었습니다! 밖으로 밝혀지면, 다른 어떤 것에서도 그렇게 잘 작동하지 않지만 내 발에있는 것과 같은 크기의 발이 있습니다. 뒤늦은 길에서 벗어나면, 임의로 2x2를 선택하는 것은 내 자신의 잘못입니다.
여기에 그것이 잘못되는 좋은 예가 있습니다. 손톱이 발가락으로 인식되고 '발 뒤꿈치'가 너무 넓어서 두 번 인식됩니다!
발이 너무 커서 두 개의 겹침없이 2x2 크기를 취하면 일부 발가락이 두 번 감지됩니다. 다른 방법으로는, 작은 개에서 그것은 종종 5x 발가락을 찾는데 실패합니다. 나는 발가락이 2x2 영역이 너무 크다고 생각합니다.
후내 모든 측정에 대해 현재 솔루션을 시험해보기나는 거의 모든 나의 작은 개를 위해 그것이 5 번째 발가락을 찾지 못했고, 큰 개를위한 충격의 50 % 이상에서 더 많이 발견 할 것이라고 엄청나게 결론에 도달했습니다!
그래서 분명히 그것을 바꿀 필요가 있습니다. 내 자신의 추측은neighborhood
작은 개는 작은 것이고 큰 개는 큰 것입니다. 그러나generate_binary_structure
배열의 크기를 변경시키지 않을 것입니다.
따라서 다른 사람들이 발가락을 찾는데 더 좋은 제안을하기를 희망합니다. 아마도 발 크기의 발가락 영역을 가질 수 있을까요?
피크를 사용하여국부 최대 필터. 다음은 네 발 앞다리의 첫 데이터 세트 결과입니다.
나 또한 9 발의 두 번째 데이터 세트에서 실행했고그것도 잘 작동했다..
여기 당신이하는 방법입니다 :
import numpy as np
from scipy.ndimage.filters import maximum_filter
from scipy.ndimage.morphology import generate_binary_structure, binary_erosion
import matplotlib.pyplot as pp
#for some reason I had to reshape. Numpy ignored the shape header.
paws_data = np.loadtxt("paws.txt").reshape(4,11,14)
#getting a list of images
paws = [p.squeeze() for p in np.vsplit(paws_data,4)]
def detect_peaks(image):
"""
Takes an image and detect the peaks usingthe local maximum filter.
Returns a boolean mask of the peaks (i.e. 1 when
the pixel's value is the neighborhood maximum, 0 otherwise)
"""
#define an 8-connected neighborhood
neighborhood = generate_binary_structure(2,2)
#apply the local maximum filter; all pixel of maximal value
#in their neighborhood are set to 1
local_max = maximum_filter(image, footprint=neighborhood)==image
#local_max is a mask that contains the peaks we are
#looking for, but also the background.
#In order to isolate the peaks we must remove the background from the mask.
#we create the mask of the background
background = (image==0)
#a little technicality: we must erode the background in order to
#successfully subtract it form local_max, otherwise a line will
#appear along the background border (artifact of the local maximum filter)
eroded_background = binary_erosion(background, structure=neighborhood, border_value=1)
#we obtain the final mask, containing only peaks,
#by removing the background from the local_max mask (xor operation)
detected_peaks = local_max ^ eroded_background
return detected_peaks
#applying the detection and plotting results
for i, paw in enumerate(paws):
detected_peaks = detect_peaks(paw)
pp.subplot(4,2,(2*i+1))
pp.imshow(paw)
pp.subplot(4,2,(2*i+2) )
pp.imshow(detected_peaks)
pp.show()
후에해야 할 일은 사용하는 것뿐입니다.scipy.ndimage.measurements.label
마스크에 모든 별개의 객체에 라벨을 붙입니다. 그런 다음 개별적으로 게임을 할 수 있습니다.
노트배경이 시끄럽지 않기 때문에이 방법이 잘 작동합니다. 만약 그렇다면 백그라운드에서 다른 원치 않는 봉우리를 감지 할 수 있습니다. 또 다른 중요한 요소는이웃. 피크 크기가 변경되면 조정해야합니다 (대략 비례해야합니다).
regmax
...에서피 몰프. - gnovice
데이터 파일:paw.txt. 소스 코드:
from scipy import *
from operator import itemgetter
n = 5 #how many fingers are we looking for
d = loadtxt("paw.txt")
width, height = d.shape
#Create an array where every element is a sum of 2x2 squares.
fourSums = d[:-1,:-1] + d[1:,:-1] + d[1:,1:] + d[:-1,1:]
#Find positions of the fingers.
#Pair each sum with its position number (from 0 to width*height-1),
pairs = zip(arange(width*height), fourSums.flatten())
#Sort by descending sum value, filter overlapping squares
def drop_overlapping(pairs):
no_overlaps = []
def does_not_overlap(p1, p2):
i1, i2 = p1[0], p2[0]
r1, col1 = i1 / (width-1), i1 % (width-1)
r2, col2 = i2 / (width-1), i2 % (width-1)
return (max(abs(r1-r2),abs(col1-col2)) >= 2)
for p in pairs:
if all(map(lambda prev: does_not_overlap(p,prev), no_overlaps)):
no_overlaps.append(p)
return no_overlaps
pairs2 = drop_overlapping(sorted(pairs, key=itemgetter(1), reverse=True))
#Take the first n with the heighest values
positions = pairs2[:n]
#Print results
print d, "\n"
for i, val in positions:
row = i / (width-1)
column = i % (width-1)
print "sum = %f @ %d,%d (%d)" % (val, row, column, i)
print d[row:row+2,column:column+2], "\n"
산출겹치지 않고. 동일한 영역이 예제와 같이 선택되어있는 것으로 보입니다.
까다로운 부분은 모든 2x2 제곱의 합을 계산하는 것입니다. 네가 그들 모두를 필요로한다고 생각했기 때문에 겹칠 수도있다. 조각을 사용하여 원본 2D 배열의 첫 번째 / 마지막 열과 행을 잘라내어 모두 겹치고 합계를 계산했습니다.
더 잘 이해하려면 3x3 배열을 이미징하십시오.
>>> a = arange(9).reshape(3,3) ; a
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
그런 다음 조각을 찍을 수 있습니다.
>>> a[:-1,:-1]
array([[0, 1],
[3, 4]])
>>> a[1:,:-1]
array([[3, 4],
[6, 7]])
>>> a[:-1,1:]
array([[1, 2],
[4, 5]])
>>> a[1:,1:]
array([[4, 5],
[7, 8]])
이제 여러분은 그것들을 하나 위에 겹치게하고 같은 위치에 원소들을 합친다 고 상상해보십시오. 이 합계는 같은 위치의 왼쪽 위 모서리와 2x2 사각형에 대해 정확히 같은 합계가됩니다.
>>> sums = a[:-1,:-1] + a[1:,:-1] + a[:-1,1:] + a[1:,1:]; sums
array([[ 8, 12],
[20, 24]])
2x2 이상의 정사각형을 사용하면max
최대 값을 찾으려면sort
, 또는sorted
봉우리를 찾으러.
봉우리의 위치를 기억하기 위해 모든 값 (합계)과 평평한 배열의 서수 위치를 결합합니다 (zip
). 그런 다음 결과를 인쇄 할 때 행 / 열 위치를 다시 계산합니다.
2x2 사각형이 겹치도록 허용했습니다. 편집 된 버전은 중복되지 않는 사각형 만 결과에 표시되도록 일부 필터를 걸러냅니다.
또 다른 문제는 모든 봉우리에서 손가락이 될 가능성이있는 것을 선택하는 방법입니다. 나는 일할 수도 있고 안할 수도있는 생각이 있습니다. 지금 당장 구현할 시간이 없으므로 단지 의사 코드 일뿐입니다.
나는 앞쪽의 손가락이 거의 완벽한 원 위에 머물러 있다면 뒤쪽의 손가락이 그 원 안에 있어야한다는 것을 알았다. 또한, 프론트 핑거는 거의 동일하게 이격되어 있습니다. 이러한 휴리스틱 속성을 사용하여 손가락을 탐지하려고 시도 할 수 있습니다.
의사 코드 :
select the top N finger candidates (not too many, 10 or 12)
consider all possible combinations of 5 out of N (use itertools.combinations)
for each combination of 5 fingers:
for each finger out of 5:
fit the best circle to the remaining 4
=> position of the center, radius
check if the selected finger is inside of the circle
check if the remaining four are evenly spread
(for example, consider angles from the center of the circle)
assign some cost (penalty) to this selection of 4 peaks + a rear finger
(consider, probably weighted:
circle fitting error,
if the rear finger is inside,
variance in the spreading of the front fingers,
total intensity of 5 peaks)
choose a combination of 4 peaks + a rear peak with the lowest penalty
이것은 무차별 대입 방식입니다. N이 비교적 작다면, 나는 그것이 가능하다고 생각합니다. N = 12의 경우, C_12 ^ 5 = 792 개의 조합이 있으며, 배의 손가락을 선택하는 5 가지 방법이 있으므로 모든 발에 대해 3960 가지의 경우를 평가할 수 있습니다.
이것은이미지 등록 문제. 일반적인 전략은 다음과 같습니다.
여기 대략적인 접근 방식이 있습니다., "가능한 일을 할 수있는 멍청한 일":
방향 문제를 해결하기 위해 기본 방향 (북쪽, 북쪽 동쪽 등)에 대해 8 가지 정도의 초기 설정을 할 수 있습니다. 각각 하나씩 실행하고 둘 이상의 발가락이 같은 픽셀에서 끝나는 결과를 버립니다. 나는 이것에 대해 좀 더 생각할 것이지만, 이런 종류의 것은 여전히 이미지 처리에서 연구되고있다. - 정답은 없다!
약간 더 복잡한 아이디어 : (가중치 적용) K- 평균 클러스터링.그렇게 나쁘진 않아.
그런 다음 수렴 될 때까지 반복합니다.
이 방법은 거의 확실한 결과를 얻을 수 있으며 발가락을 식별하는 데 도움이 될 수있는 각 클러스터의 질량을 얻습니다.
(다시 말하자면, 앞에서 클러스터 수를 지정했습니다. 클러스터링에서는 어느 정도 밀도를 지정해야합니다.이 경우 적합한 클러스터 수를 선택하거나 클러스터 반경을 선택하고 끝나는 수를 확인하십시오 후자의 예는 다음과 같습니다.평균 이동.)
구현 세부 사항 또는 기타 세부 사항이 부족하여 죄송합니다. 나는 이것을 코드화 하겠지만 마감 기한이있다. 다음 주까지 일한 것이 없다면 알려주세요.
이 문제는 물리학 자에 의해 어느 정도 깊이 연구되었다. 에서 좋은 구현이 있습니다.뿌리. 을보세요TSpectrum수업 (특히TSpectrum2귀하의 경우) 및 해당 설명서가 필요합니다.
참고 문헌 :
... 그리고 NIM 구독에 액세스 할 수없는 사람들을 위해 :
여기에 아이디어가 있습니다. 이미지의 (이산적인) 라플라스를 계산합니다. 나는 원래의 이미지보다 더 극적인 방식으로 최대치에서 (음수로) 커질 것으로 기대합니다. 따라서 맥시마를 쉽게 찾을 수 있습니다.
다른 아이디어가 있습니다. 고압 지점의 일반적인 크기를 알고있는 경우, 같은 크기의 가우스를 사용하여 이미지를 부드럽게 처리 할 수 있습니다. 이렇게하면보다 간단한 이미지 처리가 가능합니다.
지속적인 상 동성을 사용하여 데이터 세트를 분석하면 다음 결과를 얻습니다 (확대하려면 클릭).
이것은 여기에 설명 된 피크 검출 방법의 2D 버전입니다.그래서 대답. 위 그림은 영속성에 따라 정렬 된 0 차원 영구 상 동성 클래스를 보여줍니다.
scipy.misc.imresize ()를 사용하여 원본 데이터 세트의 계수를 2로 상향 조정했습니다. 그러나 4 개의 발을 하나의 데이터 세트로 간주했음을 주목하십시오. 4로 나누면 문제가 더 쉽게됩니다.
방법론.이 간단한 뒤에 숨겨진 아이디어 : 각 픽셀의 레벨을 지정하는 함수의 함수 그래프를 고려하십시오. 다음과 같이 보입니다.
이제는 높이가 255 인 수위가 지속적으로 낮은 수준으로 내려가는 것을 고려하십시오. 로컬 맥시마 섬 팝업 (출생). 안장 점에서 두 개의 섬이 병합됩니다. 우리는 더 낮은 섬이 더 높은 섬 (죽음)에 합병된다고 생각한다. 소위 영속성 다이어그램 (0 차원 차원 상 동성 클래스, 우리 섬)은 모든 섬의 출생 - 가치에 대한 죽음을 묘사합니다.
그만큼고집섬의 출생과 사망의 차이는 다음과 같다. 점의 회색 주 대각선까지의 수직 거리. 이 그림에서는 지속성을 줄임으로써 섬에 레이블을 지정합니다.
맨 처음 사진은 섬의 출생지를 보여줍니다. 이 방법은 로컬 맥시마를 제공 할뿐만 아니라 위에서 언급 한 끈기에 의해 "중요성"을 정량화합니다. 하나는 너무 낮은 지속성으로 모든 섬을 걸러냅니다. 그러나 귀하의 예에서 모든 섬 (즉, 지역 최대)은 귀하가 찾는 최고봉입니다.
파이썬 코드를 찾을 수 있습니다.이리.
내 머리 꼭대기에서 몇 가지 아이디어 만 :
좀 더 살펴보고 싶을 수도 있습니다.OpenCV, 꽤 괜찮은 Python API를 가지고 있고 유용하다고 생각되는 함수가있을 수 있습니다.
원시 데이터를 가져 주셔서 감사합니다. 나는 기차에 타고 있는데 이것은 내가 얻은 한 (내 정류장이 다가오고있다). 나는 당신의 txt 파일을 regexps로 마사지했고 시각화를위한 몇몇 자바 스크립트가있는 html 페이지에 그것을 배치했다. 일부는 나 자신과 마찬가지로 파이썬보다 쉽게 해킹 할 수 있기 때문에 여기서 공유하고 있습니다.
좋은 접근법은 척도와 회전 불변량이 될 것이며, 다음 단계는 가우시안 혼합물을 조사하는 것입니다. (각 발 패드는 가우스의 중심 임).
<html>
<head>
<script type="text/javascript" src="http://vis.stanford.edu/protovis/protovis-r3.2.js"></script>
<script type="text/javascript">
var heatmap = [[[0,0,0,0,0,0,0,4,4,0,0,0,0],
[0,0,0,0,0,7,14,22,18,7,0,0,0],
[0,0,0,0,11,40,65,43,18,7,0,0,0],
[0,0,0,0,14,61,72,32,7,4,11,14,4],
[0,7,14,11,7,22,25,11,4,14,65,72,14],
[4,29,79,54,14,7,4,11,18,29,79,83,18],
[0,18,54,32,18,43,36,29,61,76,25,18,4],
[0,4,7,7,25,90,79,36,79,90,22,0,0],
[0,0,0,0,11,47,40,14,29,36,7,0,0],
[0,0,0,0,4,7,7,4,4,4,0,0,0]
],[
[0,0,0,4,4,0,0,0,0,0,0,0,0],
[0,0,11,18,18,7,0,0,0,0,0,0,0],
[0,4,29,47,29,7,0,4,4,0,0,0,0],
[0,0,11,29,29,7,7,22,25,7,0,0,0],
[0,0,0,4,4,4,14,61,83,22,0,0,0],
[4,7,4,4,4,4,14,32,25,7,0,0,0],
[4,11,7,14,25,25,47,79,32,4,0,0,0],
[0,4,4,22,58,40,29,86,36,4,0,0,0],
[0,0,0,7,18,14,7,18,7,0,0,0,0],
[0,0,0,0,4,4,0,0,0,0,0,0,0],
],[
[0,0,0,4,11,11,7,4,0,0,0,0,0],
[0,0,0,4,22,36,32,22,11,4,0,0,0],
[4,11,7,4,11,29,54,50,22,4,0,0,0],
[11,58,43,11,4,11,25,22,11,11,18,7,0],
[11,50,43,18,11,4,4,7,18,61,86,29,4],
[0,11,18,54,58,25,32,50,32,47,54,14,0],
[0,0,14,72,76,40,86,101,32,11,7,4,0],
[0,0,4,22,22,18,47,65,18,0,0,0,0],
[0,0,0,0,4,4,7,11,4,0,0,0,0],
],[
[0,0,0,0,4,4,4,0,0,0,0,0,0],
[0,0,0,4,14,14,18,7,0,0,0,0,0],
[0,0,0,4,14,40,54,22,4,0,0,0,0],
[0,7,11,4,11,32,36,11,0,0,0,0,0],
[4,29,36,11,4,7,7,4,4,0,0,0,0],
[4,25,32,18,7,4,4,4,14,7,0,0,0],
[0,7,36,58,29,14,22,14,18,11,0,0,0],
[0,11,50,68,32,40,61,18,4,4,0,0,0],
[0,4,11,18,18,43,32,7,0,0,0,0,0],
[0,0,0,0,4,7,4,0,0,0,0,0,0],
],[
[0,0,0,0,0,0,4,7,4,0,0,0,0],
[0,0,0,0,4,18,25,32,25,7,0,0,0],
[0,0,0,4,18,65,68,29,11,0,0,0,0],
[0,4,4,4,18,65,54,18,4,7,14,11,0],
[4,22,36,14,4,14,11,7,7,29,79,47,7],
[7,54,76,36,18,14,11,36,40,32,72,36,4],
[4,11,18,18,61,79,36,54,97,40,14,7,0],
[0,0,0,11,58,101,40,47,108,50,7,0,0],
[0,0,0,4,11,25,7,11,22,11,0,0,0],
[0,0,0,0,0,4,0,0,0,0,0,0,0],
],[
[0,0,4,7,4,0,0,0,0,0,0,0,0],
[0,0,11,22,14,4,0,4,0,0,0,0,0],
[0,0,7,18,14,4,4,14,18,4,0,0,0],
[0,4,0,4,4,0,4,32,54,18,0,0,0],
[4,11,7,4,7,7,18,29,22,4,0,0,0],
[7,18,7,22,40,25,50,76,25,4,0,0,0],
[0,4,4,22,61,32,25,54,18,0,0,0,0],
[0,0,0,4,11,7,4,11,4,0,0,0,0],
],[
[0,0,0,0,7,14,11,4,0,0,0,0,0],
[0,0,0,4,18,43,50,32,14,4,0,0,0],
[0,4,11,4,7,29,61,65,43,11,0,0,0],
[4,18,54,25,7,11,32,40,25,7,11,4,0],
[4,36,86,40,11,7,7,7,7,25,58,25,4],
[0,7,18,25,65,40,18,25,22,22,47,18,0],
[0,0,4,32,79,47,43,86,54,11,7,4,0],
[0,0,0,14,32,14,25,61,40,7,0,0,0],
[0,0,0,0,4,4,4,11,7,0,0,0,0],
],[
[0,0,0,0,4,7,11,4,0,0,0,0,0],
[0,4,4,0,4,11,18,11,0,0,0,0,0],
[4,11,11,4,0,4,4,4,0,0,0,0,0],
[4,18,14,7,4,0,0,4,7,7,0,0,0],
[0,7,18,29,14,11,11,7,18,18,4,0,0],
[0,11,43,50,29,43,40,11,4,4,0,0,0],
[0,4,18,25,22,54,40,7,0,0,0,0,0],
[0,0,4,4,4,11,7,0,0,0,0,0,0],
],[
[0,0,0,0,0,7,7,7,7,0,0,0,0],
[0,0,0,0,7,32,32,18,4,0,0,0,0],
[0,0,0,0,11,54,40,14,4,4,22,11,0],
[0,7,14,11,4,14,11,4,4,25,94,50,7],
[4,25,65,43,11,7,4,7,22,25,54,36,7],
[0,7,25,22,29,58,32,25,72,61,14,7,0],
[0,0,4,4,40,115,68,29,83,72,11,0,0],
[0,0,0,0,11,29,18,7,18,14,4,0,0],
[0,0,0,0,0,4,0,0,0,0,0,0,0],
]
];
</script>
</head>
<body>
<script type="text/javascript+protovis">
for (var a=0; a < heatmap.length; a++) {
var w = heatmap[a][0].length,
h = heatmap[a].length;
var vis = new pv.Panel()
.width(w * 6)
.height(h * 6)
.strokeStyle("#aaa")
.lineWidth(4)
.antialias(true);
vis.add(pv.Image)
.imageWidth(w)
.imageHeight(h)
.image(pv.Scale.linear()
.domain(0, 99, 100)
.range("#000", "#fff", '#ff0a0a')
.by(function(i, j) heatmap[a][j][i]));
vis.render();
}
</script>
</body>
</html>
지금까지 충분히 할 수있을 것이라고 확신하지만 k-means 클러스터링 방법을 사용하는 것이 좋습니다. k-means는 관리되지 않는 클러스터링 알고리즘으로, 데이터를 가져옵니다 (임의의 차원에서 -이 작업은 3D로 수행됩니다). 그리고 그것을 뚜렷한 경계가있는 k 개의 클러스터로 정렬합니다. 이 송곳니가 얼마나 많은 발가락을 가지고 있는지 정확히 알기 때문에 여기서는 좋습니다.
또한, 그것은 정말 좋은 Scipy에서 구현됩니다 (http://docs.scipy.org/doc/scipy/reference/cluster.vq.html).
다음은 3D 클러스터를 공간적으로 해결할 수있는 방법의 예입니다.
당신이하고 싶은 것은 조금 다르다 (2D와 압력 값 포함). 그러나 나는 여전히 당신이 그것을 할 수 있다고 생각합니다.
물리학 자의 해결책 :
위치에 따라 식별되는 5 개의 발 마커 정의X_i
임의의 위치로 초기화하십시오.
발의 위치에서 마커의 위치에 대한 어떤 상을 결합하고 마커의 중첩에 대한 약간의 처벌을 결합하는 일부 에너지 기능을 정의하십시오. 의 말을하자:
E(X_i;S)=-Sum_i(S(X_i))+alfa*Sum_ij (|X_i-Xj|<=2*sqrt(2)?1:0)
(S(X_i)
주위의 2x2 정사각형의 평균 힘X_i
,alfa
실험적으로 정점에 도달하는 매개 변수)
이제 메트로 폴리스 - 헤이스팅스의 마술을 할 시간입니다.
1. 무작위 마커를 선택하고 임의의 방향으로 한 픽셀 씩 이동합니다.
2. dE, 에너지 이동의 차이를 계산합니다.
3. 0-1에서 균일 한 난수를 가져 와서 r이라고 부릅니다.
4. 만약dE<0
또는exp(-beta*dE)>r
이동을 수락하고 1로 이동합니다. 그렇지 않은 경우 이동을 취소하고 1로 이동합니다.
마커가 발에 수렴 될 때까지 반복해야합니다. 베타는 스캐닝을 제어하여 최적화를 최적화하므로 실험적으로 최적화해야합니다. 시뮬레이션 시간 (시뮬레이션 어닐링)에 따라 지속적으로 증가 할 수도 있습니다.
거대한 망원경과 비슷한 일을 할 때 내가 사용했던 또 다른 접근 방식이있다.
1) 가장 높은 픽셀을 찾습니다. 일단 당신이 그것을 가지고 있다면, 2x2 (아마도 2x2 합을 최대화)에 가장 적합한 것을 주위에서 검색하거나, 가장 높은 픽셀을 중심으로 한 4x4의 하위 영역 내부에 2d 가우스 적합을하십시오.
그런 다음 피크 센터에서 발견 된 2x2 픽셀을 0 (또는 3x3)으로 설정합니다.
1)로 돌아가서 가장 높은 피크가 소음 임계 값 아래로 떨어지거나 필요한 모든 발가락을 가질 때까지 반복하십시오.
훈련 데이터를 만들 수 있다면 신경망으로 시도해 볼 가치가 있습니다.하지만 손으로 많은 샘플이 필요합니다.
대략적인 개요 ...
연결된 구성 요소 알고리즘을 사용하여 각 발 부위를 분리하고 싶을 것입니다. wiki는 여기에 약간의 코드가있는 괜찮은 설명을했습니다 :http://en.wikipedia.org/wiki/Connected_Component_Labeling
4 또는 8 연결성을 사용할 것인지에 대한 결정을 내려야합니다. 개인적으로, 나는 대부분의 문제 때문에 6 연결성을 선호한다. 어쨌든 일단 각각의 "paw print"를 연결 영역으로 분리하면 영역을 반복하고 최대 값을 찾는 것이 쉬워야합니다. 일단 최대 값을 찾으면 주어진 "발가락"으로 식별하기 위해 미리 지정된 임계 값에 도달 할 때까지 반복적으로 영역을 확대 할 수 있습니다.
여기서 하나의 미묘한 문제는 컴퓨터 비전 기술을 사용하여 무언가를 오른쪽 / 왼쪽 / 앞 / 뒤 발로 식별하고 개인 발가락을 살펴보기 시작하면 회전, 기울임 및 번역을 고려해야한다는 것입니다. 이것은 소위 "순간들"의 분석을 통해 성취된다. 비전 애플리케이션에서 고려해야 할 몇 가지 다른 순간이 있습니다.
중심 순간 : 번역 불변 정규화 된 순간 : 스케일링 및 변환 불변 순간 : 번역, 스케일 및 회전 불변
순간에 대한 더 많은 정보는 위키에서 "이미지 모멘트"를 검색하여 찾을 수 있습니다.
아마도 Gaussian Mixture Models와 같은 것을 사용할 수 있습니다. 다음은 GMM을 수행하기위한 Python 패키지입니다 (Google 검색 만 했음).http://www.ar.media.kyoto-u.ac.jp/members/david/softwares/em/
글쎄, 여기에 간단하고 끔찍하게 효율적인 코드가 있지만,이 크기의 데이터 세트라면 괜찮습니다.
import numpy as np
grid = np.array([[0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0.4,0.4,0.4,0,0,0],
[0,0,0,0,0.4,1.4,1.4,1.8,0.7,0,0,0,0,0],
[0,0,0,0,0.4,1.4,4,5.4,2.2,0.4,0,0,0,0],
[0,0,0.7,1.1,0.4,1.1,3.2,3.6,1.1,0,0,0,0,0],
[0,0.4,2.9,3.6,1.1,0.4,0.7,0.7,0.4,0.4,0,0,0,0],
[0,0.4,2.5,3.2,1.8,0.7,0.4,0.4,0.4,1.4,0.7,0,0,0],
[0,0,0.7,3.6,5.8,2.9,1.4,2.2,1.4,1.8,1.1,0,0,0],
[0,0,1.1,5,6.8,3.2,4,6.1,1.8,0.4,0.4,0,0,0],
[0,0,0.4,1.1,1.8,1.8,4.3,3.2,0.7,0,0,0,0,0],
[0,0,0,0,0,0.4,0.7,0.4,0,0,0,0,0,0]])
arr = []
for i in xrange(grid.shape[0] - 1):
for j in xrange(grid.shape[1] - 1):
tot = grid[i][j] + grid[i+1][j] + grid[i][j+1] + grid[i+1][j+1]
arr.append([(i,j),tot])
best = []
arr.sort(key = lambda x: x[1])
for i in xrange(5):
best.append(arr.pop())
badpos = set([(best[-1][0][0]+x,best[-1][0][1]+y)
for x in [-1,0,1] for y in [-1,0,1] if x != 0 or y != 0])
for j in xrange(len(arr)-1,-1,-1):
if arr[j][0] in badpos:
arr.pop(j)
for item in best:
print grid[item[0][0]:item[0][0]+2,item[0][1]:item[0][1]+2]
나는 기본적으로 왼쪽 위의 위치와 각 2x2 사각형의 합으로 배열을 만들고 합계로 정렬합니다. 그런 다음 2x2 크기의 사각형을 가장 높은 합계로 채우고best
배열을 제거하고 제거한 다른 모든 2x2 사각형을 제거합니다.
마지막 발 (첫 번째 그림의 맨 오른쪽에 가장 작은 합이있는 것)을 제외하고는 잘 작동하는 것으로 보입니다. 더 큰 합계를 가진 다른 2x2 정사각형이 2 개 있음이 밝혀졌습니다. 서로). 그 중 하나는 여전히 2x2 정사각형에서 하나의 정사각형을 선택하지만 다른 정사각형은 왼쪽에서 벗어납니다. 다행히 운이 좋다면 원하는 것을 더 많이 선택하는 것으로 보입니다.하지만 실제로는 항상 원하는 것을 얻기 위해 다른 아이디어가 필요할 수 있습니다.
jetxee의 알고리즘을 사용하면 약간의 속임수를 쓸 수 있습니다. 그는 처음 세 발가락을 잘 찾아 냈고, 네 번째 발가락이 어디에서 벗어 났는지 추측 할 수 있어야합니다.
재미있는 문제. 내가 시도 할 해결책은 다음과 같다.
2D 가우시안 마스크가있는 회선과 같은 저역 통과 필터를 적용합니다. 이것은 (아마, 반드시 부동 소수점 일 필요는 없다) 값을 줄 것이다.
각 발 패드 (또는 발가락)의 알려진 근사 반경을 사용하여 2D 비 - 최대 억제를 수행합니다.
이것은 가까이에있는 다수의 후보자없이 최대의 직책을 제공해야합니다. 명확하게하기 위해 1 단계에서 마스크 반경도 2 단계에서 사용한 반경과 비슷해야합니다.이 반지름은 선택 가능하거나 수의사가 미리 명시 적으로 측정 할 수 있습니다 (나이 / 번식 / 기타 등으로 다를 수 있음).
제안 된 솔루션 중 일부 (평균 이동, 신경망 등)는 어느 정도 작동하지만 지나치게 복잡하고 이상적이지는 않습니다.
그냥 파이썬으로 이미지에서 로컬 맥시마를 찾는 멋진 옵션이 있다는 것을 여러분에게 말하고 싶습니다.
from skimage.feature import peak_local_max
또는 skimage 0.8.0
from skimage.feature.peak import peak_local_max
http://scikit-image.org/docs/0.8.0/api/skimage.feature.peak.html
어쩌면 순진한 접근만으로도 충분합니다. 비행기에있는 모든 2x2 정사각형의 목록을 작성하고 합계 (내림차순)로 정렬하십시오.
먼저, "발 목록"에 가장 높은 값의 사각형을 선택하십시오. 그런 다음 이전에 발견 된 사각형 중 하나와 교차하지 않는 다음으로 우수한 사각형 중 4 개를 반복하여 선택합니다.
단계별로 진행하는 경우 : 먼저 전역 최대 값을 찾고 필요한 경우 주변 값을 처리 한 다음 발견 된 영역을 0으로 설정하고 다음 값을 위해 반복합니다.
이 질문에 대한 대답은 확실하지 않지만 이웃이없는 최고봉을 찾을 수있는 것처럼 보입니다.
여기에 요지가 있습니다.Ruby에 있지만, 그 아이디어는 분명해야합니다.
require 'pp'
NUM_PEAKS = 5
NEIGHBOR_DISTANCE = 1
data = [[1,2,3,4,5],
[2,6,4,4,6],
[3,6,7,4,3],
]
def tuples(matrix)
tuples = []
matrix.each_with_index { |row, ri|
row.each_with_index { |value, ci|
tuples << [value, ri, ci]
}
}
tuples
end
def neighbor?(t1, t2, distance = 1)
[1,2].each { |axis|
return false if (t1[axis] - t2[axis]).abs > distance
}
true
end
#convert the matrix into a sorted list of tuples (value, row, col), highest peaks first
sorted = tuples(data).sort_by { |tuple| tuple.first }.reverse
#the list of peaks that don't have neighbors
non_neighboring_peaks = []
sorted.each { |candidate|
#always take the highest peak
if non_neighboring_peaks.empty?
non_neighboring_peaks << candidate
puts "took the first peak: #{candidate}"
else
#check that this candidate doesn't have any accepted neighbors
is_ok = true
non_neighboring_peaks.each { |accepted|
if neighbor?(candidate, accepted, NEIGHBOR_DISTANCE)
is_ok = false
break
end
}
if is_ok
non_neighboring_peaks << candidate
puts "took #{candidate}"
else
puts "denied #{candidate}"
end
end
}
pp non_neighboring_peaks