767

나는 개 발 아래 압력을 측정하는 수의과 클리닉을 돕고 있습니다. 저는 데이터 분석을 위해 파이썬을 사용합니다. 이제는 발을 (해부학적인) 하위 영역으로 나누려고 노력했습니다.

각 발에 대한 2D 배열을 만들었습니다.이 배열은 시간에 따라 발에 의해로드 된 각 센서의 최대 값으로 구성됩니다. 다음은 한 발의 예입니다. Excel을 사용하여 '탐지'하려는 영역을 그렸습니다. 이것들은 로컬 맥시마와 함께 센서 주위에 2 x 2 박스이며, 함께 최대 합계를가집니다.

alt text

그래서 약간의 실험을 시도하고 각 열과 행의 최대 값을 찾도록 결정했습니다 (발 모양 때문에 한 방향으로 볼 수 없음). 이것은 분리 발가락의 위치를 '감지'하는 것처럼 보이지만 이웃 센서를 표시합니다.

alt text

파이썬에게이 최대 값 중 어느 것이 내가 원하는 값인지를 알려주는 가장 좋은 방법은 무엇일까요?

참고 : 2x2 정사각형은 서로 구별되어야하기 때문에 겹칠 수 없습니다!

또한 편의상 2x2를 사용했는데 더 많은 고급 솔루션을 사용할 수는 있지만 간단히 인간 운동 과학자이므로 실제 프로그래머 나 수학자가 아니므로 '단순하게'유지하십시오.

여기에함께로드 할 수있는 버전np.loadtxt


결과

그래서 @ jextee의 솔루션을 시도했습니다 (아래 결과 참조). 보시다시피 앞 발에 매우 효과적이지만 뒷다리에는 잘 작용하지 않습니다.

더 구체적으로, 네 번째 발가락의 작은 피크를 인식 할 수 없습니다. 이것은 분명히 루프가 가장 낮은 값으로 내려가는 것을 고려하지 않고이 값이 가장 아래쪽을 향하는 것처럼 보입니다.

누구든지 @ jextee의 알고리즘을 조정하는 방법을 알고 있으므로 네 번째 발가락도 찾을 수 있을까요?

alt text

아직 다른 시험을 진행하지 않았으므로 다른 샘플을 제공 할 수 없습니다. 그러나 전에 내가 준 데이터는 각 발의 평균입니다. 이 파일은 접시와 접촉 한 순서대로 9 발의 최대 데이터를 가진 배열입니다.

이 이미지는 그들이 공간적으로 판 위에 펼쳐진 모습을 보여줍니다.

alt text

최신 정보:

관심있는 사람을 위해 블로그를 만들었습니다.모든 원시 측정으로 SkyDrive를 설정했습니다.따라서 더 많은 데이터를 요구하는 모든 사람에게 : 더 많은 힘을!


새로운 업데이트:

그래서 도움에 관한 내 질문에 관한발 감지발 정렬, 마침내 모든 발에 대한 발가락 감지를 확인할 수있었습니다! 밖으로 밝혀지면, 다른 어떤 것에서도 그렇게 잘 작동하지 않지만 내 발에있는 것과 같은 크기의 발이 있습니다. 뒤늦은 길에서 벗어나면, 임의로 2x2를 선택하는 것은 내 자신의 잘못입니다.

여기에 그것이 잘못되는 좋은 예가 있습니다. 손톱이 발가락으로 인식되고 '발 뒤꿈치'가 너무 넓어서 두 번 인식됩니다!

alt text

발이 너무 커서 두 개의 겹침없이 2x2 크기를 취하면 일부 발가락이 두 번 감지됩니다. 다른 방법으로는, 작은 개에서 그것은 종종 5x 발가락을 찾는데 실패합니다. 나는 발가락이 2x2 영역이 너무 크다고 생각합니다.

내 모든 측정에 대해 현재 솔루션을 시험해보기나는 거의 모든 나의 작은 개를 위해 그것이 5 번째 발가락을 찾지 못했고, 큰 개를위한 충격의 50 % 이상에서 더 많이 발견 할 것이라고 엄청나게 결론에 도달했습니다!

그래서 분명히 그것을 바꿀 필요가 있습니다. 내 자신의 추측은neighborhood작은 개는 작은 것이고 큰 개는 큰 것입니다. 그러나generate_binary_structure배열의 크기를 변경시키지 않을 것입니다.

따라서 다른 사람들이 발가락을 찾는데 더 좋은 제안을하기를 희망합니다. 아마도 발 크기의 발가락 영역을 가질 수 있을까요?


  • 이것은 그렇게 사소하지만 흥미로운 것처럼 보입니다. 파이썬에서 쉽게 읽을 수있는 형식으로 더 많은 데이터 세트 (paw)를 제공 할 수 있습니까? 그래서 나는 약간의 아이디어를 시험해 볼 수 있었다. - Christian
  • 오랫동안 읽은 재미있는 질문 중 하나입니다. 그것은 심지어 일러스트가 함께 제공됩니다. 내 모자는 너에게 떨어져있다. - wheaties
  • 타당성 조사를 수행함에 따라 무엇이든 실제로 진행됩니다. 그래서 하위 지역을 포함하여 압력을 정의하는 많은 방법을 모색하고 있습니다. 또한 나는 엄지 발가락 '을 구별 할 수 있어야합니다. 그리고 작은 발가락 ' 측면을 측정하여 방향을 추정합니다. 그러나 이전에는이 방법이 없었기 때문에 우리가 찾을 수있는 것을 말하지 않습니다 :-) - Ivo Flipse
  • @Ivo : 우리는 너무 익숙하지 않은 " 안녕하세요, 세계 '를 어떻게 인쇄하나요? VB " 이것이 신선한 공기의 숨결이라는 질문. - Pavel Minaev
  • 나는 현상금을 나누기를 바란다. 분명히 여기에 하나 이상의 대답이 있기 때문이다. 그 능력이 부족하기 때문에 나는 가장 높은 득표를 한 답을 얻는다. - Pavel Minaev

21 답변


270

피크를 사용하여국부 최대 필터. 다음은 네 발 앞다리의 첫 데이터 세트 결과입니다.Peaks detection result

나 또한 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마스크에 모든 별개의 객체에 라벨을 붙입니다. 그런 다음 개별적으로 게임을 할 수 있습니다.

노트배경이 시끄럽지 않기 때문에이 방법이 잘 작동합니다. 만약 그렇다면 백그라운드에서 다른 원치 않는 봉우리를 감지 할 수 있습니다. 또 다른 중요한 요소는이웃. 피크 크기가 변경되면 조정해야합니다 (대략 비례해야합니다).


  • +1 멋진 결과. 내 첫번째 생각은 다음과 같은 지역 맥시마 찾기 알고리즘을 사용하는 것이 었습니다.regmax...에서피 몰프. - gnovice
  • 이것은 매우 유망한 것으로 보입니다. 더 많은 측정 값을 분석하려고합니다. 그래서 그것이 유지되는지를 볼 수 있습니다 :-) - Ivo Flipse
  • doc의 설명에서 @gnovice를 사용하여 local_max 행과 동일한 작업을 수행하는 것으로 알고 있습니다. - Ivan
  • 침식 된 배경의 이미지를 보여줄 수 있습니까? '침식'의 의미를 이해하려고 노력 중입니다. - lennon310
  • (eroded_background ^ local_peaks)보다 간단한 해결책이 있습니다. 그냥 해보세요 (전경 및 국부 피크) - Ryan Soklaski

42

해결책

데이터 파일: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 가지의 경우를 평가할 수 있습니다.


  • 그는 결과 목록이 주어지면 앞발을 수동으로 걸러 내야 만합니다 ... 4 개의 최상위 결과를 선택하면 최대 값 6.8을 포함하는 2x2 정사각형을 구성 할 수있는 4 가지 가능성이 있습니다 - Johannes Charra
  • 통계를 원할 경우 같은 지역을 사용하고 싶지 않기 때문에 지역을 비교하고 싶습니다. :-) 2x2 상자는 겹칠 수 없습니다. - Ivo Flipse
  • 필요한 경우 중첩되지 않는 영역 만 필터링하는 코드 스 니펫을 작성할 수 있습니다. 조금 후에. - sastanin
  • 나는 그것을 시험해 보았다. 그리고 그것은 앞발을 위해 일하는 것처럼 보인다. 그러나 뒤의 것을 위해 그렇게 적지 않다. 어디를보아야하는지 알 수있는 방법을 찾아야합니다. - Ivo Flipse
  • 의사 코드로 손가락을 감지 할 수있는 방법을 설명했습니다. 네가 좋아한다면, 내일 저녁에 그것을 시행하려고 할 수도있다. - sastanin

27

이것은이미지 등록 문제. 일반적인 전략은 다음과 같습니다.

  • 알려진 예나, 어떤 종류의사전의데이터에.
  • 예제에 데이터를 맞추거나 데이터에 예제를 맞 춥니 다.
  • 귀하의 데이터가대충처음부터 정렬.

여기 대략적인 접근 방식이 있습니다., "가능한 일을 할 수있는 멍청한 일":

  • 대략 5 개의 발가락 좌표로 시작하십시오.
  • 각각 하나씩, 언덕 꼭대기까지 반복적으로 올라가십시오. 즉 주어진 현재 위치는 그 값이 현재 픽셀보다 큰 경우 최대 인접 픽셀로 이동합니다. 발가락 좌표가 움직이지 않을 때 멈추십시오.

방향 문제를 해결하기 위해 기본 방향 (북쪽, 북쪽 동쪽 등)에 대해 8 가지 정도의 초기 설정을 할 수 있습니다. 각각 하나씩 실행하고 둘 이상의 발가락이 같은 픽셀에서 끝나는 결과를 버립니다. 나는 이것에 대해 좀 더 생각할 것이지만, 이런 종류의 것은 여전히 이미지 처리에서 연구되고있다. - 정답은 없다!

약간 더 복잡한 아이디어 : (가중치 적용) K- 평균 클러스터링.그렇게 나쁘진 않아.

  • 5 개의 발가락 좌표로 시작하지만, 이제는 "클러스터 센터"입니다.

그런 다음 수렴 될 때까지 반복합니다.

  • 각 픽셀을 가장 가까운 클러스터에 할당합니다 (각 클러스터에 대한 목록 만 작성).
  • 각 클러스터의 질량 중심을 계산합니다. 각 클러스터의 경우 다음과 같습니다. Sum (좌표 * 강도 값) / Sum (좌표)
  • 각 클러스터를 새로운 질량 중심으로 이동하십시오.

이 방법은 거의 확실한 결과를 얻을 수 있으며 발가락을 식별하는 데 도움이 될 수있는 각 클러스터의 질량을 얻습니다.

(다시 말하자면, 앞에서 클러스터 수를 지정했습니다. 클러스터링에서는 어느 정도 밀도를 지정해야합니다.이 경우 적합한 클러스터 수를 선택하거나 클러스터 반경을 선택하고 끝나는 수를 확인하십시오 후자의 예는 다음과 같습니다.평균 이동.)

구현 세부 사항 또는 기타 세부 사항이 부족하여 죄송합니다. 나는 이것을 코드화 하겠지만 마감 기한이있다. 다음 주까지 일한 것이 없다면 알려주세요.


  • 문제는 발이 방향을 바꾸고 시작하기에 올바른 발의 교정 / 기준선을 갖고 있지 않다는 것입니다. 게다가 많은 이미지 인식 알고리즘이 내 리그에서 약간 벗어날 까봐 두렵습니다. - Ivo Flipse
  • "거칠고 준비가 된" 접근법은 매우 간단합니다. 어쩌면 아이디어를 잘 전달하지 못했을 수도 있습니다. 몇 가지 의사 코드를 설명해 보겠습니다. - CakeMaster
  • 당신의 제안이 뒷다리의 인식을 고치는 데 도움이 될 것 같은 느낌이 들지만, 나는 단지 어떻게하면 ' - Ivo Flipse
  • 다른 아이디어를 추가했습니다. 그런데 좋은 데이터가있는 경우 온라인 어딘가에 넣는 것이 좋습니다. 이미지 처리 / 기계 학습을 공부하는 사람들에게 유용 할 수 있으며, 더 많은 코드를 얻을 수도 있습니다 ... - CakeMaster
  • 나는 단순한 Wordpress 블로그에 내 데이터 처리를 쓰는 것에 대해 생각하고 있었고, 단순히 다른 사람들을 위해 쓰고 싶었고 어쨌든 그것을 써야만했다. 나는 당신의 제안을 모두 좋아하지만, 마감 시간없이 누군가를 기다려야 할까 봐 걱정합니다 ;-) - Ivo Flipse

12

이 문제는 물리학 자에 의해 어느 정도 깊이 연구되었다. 에서 좋은 구현이 있습니다.뿌리. 을보세요TSpectrum수업 (특히TSpectrum2귀하의 경우) 및 해당 설명서가 필요합니다.

참고 문헌 :

  1. M.Morhac 등 : 다차원 동시 일치 감마선 스펙트럼에 대한 배경 제거 방법. 원자력 기기 및 방법 물리학 연구 A 401 (1997) 113-132.
  2. M.Morhac et al .: 효율적인 일차원 및 이차원 Gold deconvolution과 감마선 스펙트럼 분해에의 적용. 원자력 기기 및 방법 물리학 연구 A 401 (1997) 385-408.
  3. M.Morhac et al .: 다차원 일치의 감마선 스펙트럼에서 피크의 확인. 연구 물리학 A 443 (2000), 108-125에있는 핵기구 및 방법.

... 그리고 NIM 구독에 액세스 할 수없는 사람들을 위해 :


  • 기사를 보면서 나는 여기에서 시도한 것과 같은 데이터 처리를 설명하는 것처럼 보이지만 내 프로그래밍 기술을 크게 뛰어 넘을까 두려워한다. ( - Ivo Flipse
  • @Ivo : 직접 구현하려하지 않았습니다. 나는 ROOT 만 사용한다. 파이썬 바인딩이 있습니다. less-than-less이지만, ROOT는 꽤 무거운 패키지라는 것을 알고 있어야합니다. - dmckee
  • @Ivo Flipse : 나는 dmckee에 동의합니다. 다른 답에는 유망한 리드가 많습니다. 그들이 모두 실패하고 시간을 투자하는 느낌이 든다면, 당신은 ROOT를 탐구 할 수 있고, 아마도 당신이 필요로하는 것을 할 것입니다. 파이썬 바인딩 (자연스러운 C ++이 아닌)을 통해 ROOT를 배우려는 사람을 알지 못해서 운이 좋았을 것입니다. - physicsmichael

10

여기에 아이디어가 있습니다. 이미지의 (이산적인) 라플라스를 계산합니다. 나는 원래의 이미지보다 더 극적인 방식으로 최대치에서 (음수로) 커질 것으로 기대합니다. 따라서 맥시마를 쉽게 찾을 수 있습니다.

다른 아이디어가 있습니다. 고압 지점의 일반적인 크기를 알고있는 경우, 같은 크기의 가우스를 사용하여 이미지를 부드럽게 처리 할 수 있습니다. 이렇게하면보다 간단한 이미지 처리가 가능합니다.


10

지속적인 상 동성을 사용하여 데이터 세트를 분석하면 다음 결과를 얻습니다 (확대하려면 클릭).

Result

이것은 여기에 설명 된 피크 검출 방법의 2D 버전입니다.그래서 대답. 위 그림은 영속성에 따라 정렬 된 0 차원 영구 상 동성 클래스를 보여줍니다.

scipy.misc.imresize ()를 사용하여 원본 데이터 세트의 계수를 2로 상향 조정했습니다. 그러나 4 개의 발을 하나의 데이터 세트로 간주했음을 주목하십시오. 4로 나누면 문제가 더 쉽게됩니다.

방법론.이 간단한 뒤에 숨겨진 아이디어 : 각 픽셀의 레벨을 지정하는 함수의 함수 그래프를 고려하십시오. 다음과 같이 보입니다.

3D function graph

이제는 높이가 255 인 수위가 지속적으로 낮은 수준으로 내려가는 것을 고려하십시오. 로컬 맥시마 섬 팝업 (출생). 안장 점에서 두 개의 섬이 병합됩니다. 우리는 더 낮은 섬이 더 높은 섬 (죽음)에 합병된다고 생각한다. 소위 영속성 다이어그램 (0 차원 차원 상 동성 클래스, 우리 섬)은 모든 섬의 출생 - 가치에 대한 죽음을 묘사합니다.

Persistence diagram

그만큼고집섬의 출생과 사망의 차이는 다음과 같다. 점의 회색 주 대각선까지의 수직 거리. 이 그림에서는 지속성을 줄임으로써 섬에 레이블을 지정합니다.

맨 처음 사진은 섬의 출생지를 보여줍니다. 이 방법은 로컬 맥시마를 제공 할뿐만 아니라 위에서 언급 한 끈기에 의해 "중요성"을 정량화합니다. 하나는 너무 낮은 지속성으로 모든 섬을 걸러냅니다. 그러나 귀하의 예에서 모든 섬 (즉, 지역 최대)은 귀하가 찾는 최고봉입니다.

파이썬 코드를 찾을 수 있습니다.이리.


9

내 머리 꼭대기에서 몇 가지 아이디어 만 :

  • 스캔의 그래디언트 (파생물)를 취하여 잘못된 호출을 제거하는지 확인합니다.
  • 국부적 인 최대치를 취한다.

좀 더 살펴보고 싶을 수도 있습니다.OpenCV, 꽤 괜찮은 Python API를 가지고 있고 유용하다고 생각되는 함수가있을 수 있습니다.


  • 그래디언트를 사용하면 슬로프의 가파른 정도를 계산해야합니다. 일단 내가 알고있는 특정 값보다 높으면 피크 ' 나는 이것을 시도했지만 발가락 중 일부는 다른 일부 (8 N / cm)에 비해 매우 낮은 피크 (1.2 N / cm)만을 가지고 있습니다. 그렇다면 매우 낮은 그래디언트의 피크를 어떻게 처리해야합니까? - Ivo Flipse
  • 그래디언트를 직접 사용할 수 없다면 과거에 어떤 일이 일어 났는가? 그래디언트와 최대 값을 살펴 보는 것이 었습니다. 그래디언트가 로컬 극한치이고 로컬 최대치 인 경우 관심 지점에 있습니다. - ChrisC

7

원시 데이터를 가져 주셔서 감사합니다. 나는 기차에 타고 있는데 이것은 내가 얻은 한 (내 정류장이 다가오고있다). 나는 당신의 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>

alt text


  • 필자는 권장 Gaussian 기법이 작동한다는 개념의 증거라고 생각합니다. 이제 누군가가 파이썬으로 증명할 수 있다면 ;-) - Ivo Flipse

7

지금까지 충분히 할 수있을 것이라고 확신하지만 k-means 클러스터링 방법을 사용하는 것이 좋습니다. k-means는 관리되지 않는 클러스터링 알고리즘으로, 데이터를 가져옵니다 (임의의 차원에서 -이 작업은 3D로 수행됩니다). 그리고 그것을 뚜렷한 경계가있는 k 개의 클러스터로 정렬합니다. 이 송곳니가 얼마나 많은 발가락을 가지고 있는지 정확히 알기 때문에 여기서는 좋습니다.

또한, 그것은 정말 좋은 Scipy에서 구현됩니다 (http://docs.scipy.org/doc/scipy/reference/cluster.vq.html).

다음은 3D 클러스터를 공간적으로 해결할 수있는 방법의 예입니다.enter image description here

당신이하고 싶은 것은 조금 다르다 (2D와 압력 값 포함). 그러나 나는 여전히 당신이 그것을 할 수 있다고 생각합니다.


6

물리학 자의 해결책 :

위치에 따라 식별되는 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로 이동합니다.

마커가 발에 수렴 될 때까지 반복해야합니다. 베타는 스캐닝을 제어하여 최적화를 최적화하므로 실험적으로 최적화해야합니다. 시뮬레이션 시간 (시뮬레이션 어닐링)에 따라 지속적으로 증가 할 수도 있습니다.


  • 나의 예를 들어 이것이 어떻게 작동하는지 보여주기위한주의 사항? 고도의 수학이 아니기 때문에 제안한 수식을 풀 때 이미 어려움을 겪고 있습니다. ( - Ivo Flipse
  • 이것은 고등학교 수학입니다. 아마도 필자의 표기법은 단지 난독 화 된 것일뿐입니다. 나는 그것을 점검 할 계획이 있으므로, 계속 지켜봐주십시오. - mbq
  • 입자 물리학 자입니다. 오랜 시간 동안 우리 분야의 go-to 소프트웨어 도구는 PAW라고 불리우며 "마커 (marker)"라고 불리는 그래프와 관련된 개체를 가졌습니다. 당신은 내가 처음 몇 시간 동안이 대답을 얼마나 혼란스럽게하는지 상상할 수 있습니다 ... - dmckee

5

거대한 망원경과 비슷한 일을 할 때 내가 사용했던 또 다른 접근 방식이있다.

1) 가장 높은 픽셀을 찾습니다. 일단 당신이 그것을 가지고 있다면, 2x2 (아마도 2x2 합을 최대화)에 가장 적합한 것을 주위에서 검색하거나, 가장 높은 픽셀을 중심으로 한 4x4의 하위 영역 내부에 2d 가우스 적합을하십시오.

그런 다음 피크 센터에서 발견 된 2x2 픽셀을 0 (또는 3x3)으로 설정합니다.

1)로 돌아가서 가장 높은 피크가 소음 임계 값 아래로 떨어지거나 필요한 모든 발가락을 가질 때까지 반복하십시오.


  • 이 작업을 수행하는 코드 예제를 공유하는 데주의해야합니까? 내가하려는 것을 수행 할 수는 있지만 직접 코드를 작성하는 방법을 모를 수 있습니다. - Ivo Flipse
  • 나는 몇 가지 MATLAB 코드가 도움이 될 것인가? - Paulus
  • 사실 Matlab에서 일했기 때문에 이미 도움이되었습니다. 하지만 정말로 외래 함수를 사용한다면 Python으로 그것을 복제하는 것이 어려울 수도 있습니다. - Ivo Flipse

5

훈련 데이터를 만들 수 있다면 신경망으로 시도해 볼 가치가 있습니다.하지만 손으로 많은 샘플이 필요합니다.


  • 문제가 발생하면 손으로 큰 샘플에 주석을 달지 않아도됩니다. 내 문제는 것입니다 : 신경 네트워크 프로그래밍에 대해 아무것도 모르기 때문에 어떻게 구현합니까? - Ivo Flipse

5

대략적인 개요 ...

연결된 구성 요소 알고리즘을 사용하여 각 발 부위를 분리하고 싶을 것입니다. wiki는 여기에 약간의 코드가있는 괜찮은 설명을했습니다 :http://en.wikipedia.org/wiki/Connected_Component_Labeling

4 또는 8 연결성을 사용할 것인지에 대한 결정을 내려야합니다. 개인적으로, 나는 대부분의 문제 때문에 6 연결성을 선호한다. 어쨌든 일단 각각의 "paw print"를 연결 영역으로 분리하면 영역을 반복하고 최대 값을 찾는 것이 쉬워야합니다. 일단 최대 값을 찾으면 주어진 "발가락"으로 식별하기 위해 미리 지정된 임계 값에 도달 할 때까지 반복적으로 영역을 확대 할 수 있습니다.

여기서 하나의 미묘한 문제는 컴퓨터 비전 기술을 사용하여 무언가를 오른쪽 / 왼쪽 / 앞 / 뒤 발로 식별하고 개인 발가락을 살펴보기 시작하면 회전, 기울임 및 번역을 고려해야한다는 것입니다. 이것은 소위 "순간들"의 분석을 통해 성취된다. 비전 애플리케이션에서 고려해야 할 몇 가지 다른 순간이 있습니다.

중심 순간 : 번역 불변 정규화 된 순간 : 스케일링 및 변환 불변 순간 : 번역, 스케일 및 회전 불변

순간에 대한 더 많은 정보는 위키에서 "이미지 모멘트"를 검색하여 찾을 수 있습니다.


4

아마도 Gaussian Mixture Models와 같은 것을 사용할 수 있습니다. 다음은 GMM을 수행하기위한 Python 패키지입니다 (Google 검색 만 했음).http://www.ar.media.kyoto-u.ac.jp/members/david/softwares/em/


3

글쎄, 여기에 간단하고 끔찍하게 효율적인 코드가 있지만,이 크기의 데이터 세트라면 괜찮습니다.

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 정사각형에서 하나의 정사각형을 선택하지만 다른 정사각형은 왼쪽에서 벗어납니다. 다행히 운이 좋다면 원하는 것을 더 많이 선택하는 것으로 보입니다.하지만 실제로는 항상 원하는 것을 얻기 위해 다른 아이디어가 필요할 수 있습니다.


  • 나는 당신의 결과가 @ Jextee의 대답과 동일하다고 생각합니다. 아니면 적어도 그것은 그것을 테스트하는 것으로 보인다. - Ivo Flipse

3

jetxee의 알고리즘을 사용하면 약간의 속임수를 쓸 수 있습니다. 그는 처음 세 발가락을 잘 찾아 냈고, 네 번째 발가락이 어디에서 벗어 났는지 추측 할 수 있어야합니다.


3

재미있는 문제. 내가 시도 할 해결책은 다음과 같다.

  1. 2D 가우시안 마스크가있는 회선과 같은 저역 통과 필터를 적용합니다. 이것은 (아마, 반드시 부동 소수점 일 필요는 없다) 값을 줄 것이다.

  2. 각 발 패드 (또는 발가락)의 알려진 근사 반경을 사용하여 2D 비 - 최대 억제를 수행합니다.

이것은 가까이에있는 다수의 후보자없이 최대의 직책을 제공해야합니다. 명확하게하기 위해 1 단계에서 마스크 반경도 2 단계에서 사용한 반경과 비슷해야합니다.이 반지름은 선택 가능하거나 수의사가 미리 명시 적으로 측정 할 수 있습니다 (나이 / 번식 / 기타 등으로 다를 수 있음).

제안 된 솔루션 중 일부 (평균 이동, 신경망 등)는 어느 정도 작동하지만 지나치게 복잡하고 이상적이지는 않습니다.


  • 나는 convolution 행렬과 Gaussian 필터에 대한 경험이 없으므로 예제에서 어떻게 작동하는지 보여 주시겠습니까? - Ivo Flipse

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


0

어쩌면 순진한 접근만으로도 충분합니다. 비행기에있는 모든 2x2 정사각형의 목록을 작성하고 합계 (내림차순)로 정렬하십시오.

먼저, "발 목록"에 가장 높은 값의 사각형을 선택하십시오. 그런 다음 이전에 발견 된 사각형 중 하나와 교차하지 않는 다음으로 우수한 사각형 중 4 개를 반복하여 선택합니다.


  • 실제로 모든 2x2 합계를 사용하여 목록을 만들었지 만 명령을 받으면 반복적으로 비교하는 방법을 알지 못했습니다. 내 문제는 내가 그것을 분류 할 때, 나는 좌표의 흔적을 잃어 버렸다. 아마도 좌표를 키로하여 사전에 붙여 둘 수 있습니다. - Ivo Flipse
  • 그렇습니다. 어떤 종류의 사전이 필요할 것입니다. 나는 그리드의 표현이 어떤 종류의 사전이라고 이미 가정했다. - Johannes Charra
  • 위 이미지는 음각 배열입니다. 나머지는 현재 다차원 목록에 저장됩니다. 사전을 반복하는 것에 익숙하지 않더라도 그렇게하지 않는 것이 좋습니다. - Ivo Flipse

0

단계별로 진행하는 경우 : 먼저 전역 최대 값을 찾고 필요한 경우 주변 값을 처리 한 다음 발견 된 영역을 0으로 설정하고 다음 값을 위해 반복합니다.


  • 음, 0으로 설정하면 적어도 추가 계산에서 제거되므로 유용 할 것입니다. - Ivo Flipse
  • 0으로 설정하는 대신 손으로 선택한 매개 변수로 가우스 함수를 계산하고 원래 압력 판독 값에서 찾은 값을 빼낼 수 있습니다. 따라서 발가락이 센서를 누르는 경우 가장 높은 압력 점을 찾아이를 사용하여 센서에 미치는 영향을 줄여 압력 값이 높은 인접한 셀을 제거합니다.en.wikipedia.org/wiki/File:Gaussian_2d.png - Daniyar
  • @Daniyar의 샘플 데이터를 기반으로 예제를 보여주는주의? 이러한 종류의 데이터 처리에 익숙하지 않기 때문에 - Ivo Flipse

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


  • 파이썬 코드로 변환 할 수 있는지 살펴보고 다음을 시도해 보겠습니다 :-) - Ivo Flipse
  • 합리적인 길이라면 요지에 연결하는 대신 코드 자체를 게시물에 포함하십시오. - agf

연결된 질문


최근 질문