python 이미지 - 2D 배열의 피크 검출




프로세싱 튜토리얼 (18)

이 문제는 물리학 자에 의해 어느 정도 깊이 연구되었다. ROOT 에는 좋은 구현이 있습니다. 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 구독에 액세스 할 수없는 사람들을 위해 :

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

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

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

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

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

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

np.loadtxt 로로드 할 수 있는 버전이 있습니다.

결과

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

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

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

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

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

최신 정보:

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

새로운 업데이트:

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

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

발이 너무 커서 두 개의 겹침없이 2x2 크기를 취하면 일부 발가락이 두 번 감지됩니다. 다른 방법으로는 작은 강아지의 경우 5x 발가락을 찾지 못하는 경우가 종종 있는데 이는 2x2 영역이 너무 커서 원인으로 의심됩니다.

모든 나의 측정에 현재 해결책을 시험해보고 난 후에 나는 거의 모든 나의 작은 개를 위해 그것이 제 5의 발가락을 발견하지 않는다라고하는 과격한 결론에왔다. 그리고 그것은 큰 개를 위해 충격의 50 % 이상에서 더 많이 발견 할 것이다!

그래서 분명히 그것을 바꿀 필요가 있습니다. 내 자신의 추측은 neighborhood 의 크기를 작은 개는 작은 것으로, 큰 개는 큰 것으로 변경하고있었습니다. 하지만 generate_binary_structure 는 배열의 크기를 변경할 수 없습니다.

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


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

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

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

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

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


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


이 질문에 대한 대답은 확실하지 않지만, 이웃이없는 가장 높은 봉우리를 찾을 수있는 것처럼 보입니다.

여기에 요지가 있습니다. 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

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


물리학 자의 해결책 :
위치 X_i 식별되는 5 개의 발 마커를 정의하고 임의의 위치로 초기화합니다. 발의 위치에서 마커의 위치에 대한 어떤 상을 결합하고 마커의 중첩에 대한 약간의 처벌을 결합하는 일부 에너지 기능을 정의하십시오. 의 말을하자:

E(X_i;S)=-Sum_i(S(X_i))+alfa*Sum_ij (|X_i-Xj|<=2*sqrt(2)?1:0)

( S(X_i)S(X_i) 주변의 2x2 제곱근의 평균 힘이며, alfa 는 실험적으로 정점에 도달하는 매개 변수 임)

이제 메트로 폴리스 - 헤이스팅스의 마술을 할 시간입니다.
1. 무작위 마커를 선택하고 임의의 방향으로 한 픽셀 씩 이동합니다.
2. dE, 에너지 이동의 차이를 계산합니다.
3. 0-1에서 균일 한 난수를 가져 와서 r이라고 부릅니다.
4. dE<0 또는 exp(-beta*dE)>r 인 경우 이동을 수락하고 1로 이동합니다. 그렇지 않은 경우 이동을 취소하고 1로 이동합니다.
마커가 발에 수렴 될 때까지 반복해야합니다. 베타는 스캐닝을 제어하여 최적화를 최적화하므로 실험적으로 최적화해야합니다. 시뮬레이션 시간 (시뮬레이션 어닐링)에 따라 지속적으로 증가 할 수도 있습니다.


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

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

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

방법론. 이 간단한 뒤에 숨은 아이디어는 각 픽셀에 레벨을 할당하는 함수의 함수 그래프를 생각해보십시오. 다음과 같이 보입니다.

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

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

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

파이썬 코드는 here 에서 찾을 수 here .


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

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

또한 꽤 괜찮은 Python API를 가지고 있고 유용하다고 생각되는 몇 가지 기능이있을 수있는 OpenCV 살펴볼 수도 있습니다.


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

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


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


해결책

데이터 파일 : 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"

겹치는 사각형없이 Output . 동일한 영역이 예제와 같이 선택되어있는 것으로 보입니다.

일부 의견

까다로운 부분은 모든 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 를 사용하여 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 가지의 경우를 평가할 수 있습니다.


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

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



대략적인 개요 ...

연결된 구성 요소 알고리즘을 사용하여 각 발 부위를 분리하고 싶을 것입니다. 위키는 여기 (약간의 코드로)에 대한 적당한 설명을 가지고 있습니다 : http://en.wikipedia.org/wiki/Connected_Component_Labeling

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

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

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

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


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


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

또한 Scipy에서 구현되었는데, 정말 좋았습니다 ( http://docs.scipy.org/doc/scipy/reference/cluster.vq.html ).

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

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



나는 sqlalchemy 패키지 에서 많은 혜택을 얻었습니다. 그것은 객체 관계 맵퍼입니다. 이것이 의미하는 바는 개체와 데이터간에 매우 명확하고 분명한 분리를 만들 수 있다는 것입니다.

SQL 데이터베이스는 크기와 성능이 중요해질수록 개체 컬렉션과 유사하게 동작합니다. 객체 컬렉션은 테이블과 행처럼 동작하지 않으므로 더 추상화가 중요합니다. SQLAlchemy는 이러한 두 가지 원칙을 모두 수용하려고합니다.

다른 명사 (개, 측정, 판 등)를 나타내는 개체를 만들 수 있습니다. 그런 다음 sqlalchemy 구조를 통해 테이블을 작성합니다.이 구조에는 Dog 오브젝트와 연관시키려는 모든 데이터가 들어 있습니다. 마지막으로 Dog 객체와 dog_table 사이의 mapper 를 만듭니다.

예제가 없으면 이해하기 어렵습니다. 여기서는 그 중 하나를 재현하지 않겠습니다. 대신 이 사례 연구 를 읽은 다음 이 자습서를 읽어보십시오 .

현실 세계 (즉, 개체 자체)에서와 마찬가지로 Dogs Measurements 을 생각할 수있게되면 데이터를 구성하는 데이터를 분해 할 수 있습니다.

마지막으로 numpy 배열을 사용하여 특정 형식으로 데이터를 결합하지 마십시오. 대신, 간단한 숫자를 생각한 다음 필요에 따라 현재 응용 프로그램에서 요구하는 특정 형식 (모델보기 컨트롤러 패러다임의 선을 따라)으로 변환 할 수 있습니다.

행운을 빕니다!





python image-processing