2D 어레이에서의 피크 검출
저는 개발 아래 압력을 측정하는 동물 클리닉을 돕고 있어요.데이터 분석에 Python을 사용하고 있는데, 이제 발을 (해부학적) 하위 영역으로 나누려다 꼼짝할 수 없게 되었습니다.
각 손의 2D 어레이를 만들었습니다.각 센서의 최대값으로 구성되어 있습니다.다음은 Excel을 사용하여 '탐지'하고 싶은 영역을 그린 한 개의 발 예입니다.이것들은 센서 주변의 2x2 박스로 국부적인 최대값을 가지고 있으며, 합계가 가장 큽니다.
그래서 몇 가지 실험을 해보고 각 열과 열의 최대값을 찾기로 했습니다(발 모양 때문에 한 방향을 볼 수 없습니다).이것은 분리된 발가락의 위치를 꽤 잘 '탐지'하는 것처럼 보이지만, 또한 이웃의 센서들을 표시하기도 한다.
그렇다면 파이썬에게 내가 원하는 최대값을 알려 주는 가장 좋은 방법은 무엇일까요?
주의: 2x2 정사각형은 서로 다른 발가락이어야 하므로 겹칠 수 없습니다.
또, 2x2를 편의상 사용했기 때문에, 그 이상의 고도의 솔루션은 환영입니다만, 저는 단순한 휴먼·무브먼트·사이언티스트이기 때문에, 진정한 프로그래머도 아니고 수학자도 아니기 때문에, 「심플」하게 해 주세요.
결과.
그래서 @jextee의 솔루션을 사용해 보았습니다(아래 결과를 참조).보시다시피, 앞발에는 매우 효과가 있지만 뒷발에는 덜 효과가 있습니다.
좀 더 구체적으로 말하면, 네 번째 발가락인 작은 봉우리도 인식하지 못합니다.이것은 루프가 어디에 있는지 고려하지 않고 가장 낮은 값을 향해 하향으로 보이는 것에 기인합니다.
@jextee의 알고리즘을 수정하여 넷째 발가락도 찾을 수 있도록 하는 방법을 아는 사람이 있습니까?
저는 아직 다른 시험을 진행하지 않았기 때문에 다른 샘플은 공급할 수 없습니다.하지만 제가 전에 알려드린 데이터는 각 발의 평균치였습니다.이 파일은 플레이트와 접촉한 순서대로 최대 9개의 발이 있는 배열입니다.
이 이미지는 어떻게 그것들이 접시 위에 공간적으로 펼쳐져 있는지를 보여줍니다.
업데이트:
관심 있는 사람을 위한 블로그를 개설했고 모든 원시 측정치가 포함된 OneDrive를 설정했습니다.따라서 더 많은 데이터를 원하는 모든 사용자에게 더 강력한 성능을 제공합니다.
새 업데이트:
그래서 발 감지와 발 분류에 대한 질문을 받은 후, 나는 마침내 모든 발의 발 인식을 확인할 수 있었다!제 예시와 같은 크기의 발 외에는 아무 것도 잘 작동하지 않는 것으로 나타났습니다.물론, 나중에 생각해보면, 그렇게 임의로 2x2를 선택한 것은 제 잘못입니다.
여기 그것이 어디에서 잘못되는지에 대한 좋은 예가 있다: 못은 발가락으로 인식되고 있고 '굽'은 너무 넓어서 두 번 인식된다!
발이 너무 커서 겹치지 않고 2x2 크기로 찍으면 두 번 발가락을 발견할 수 있습니다.반대로, 작은 개의 경우 5번째 발가락이 발견되지 않는 경우가 많은데, 2x2 면적이 너무 넓어서 그런 것 같습니다.
내 모든 치수에 대해 현재의 해결책을 시도해 본 결과, 나는 거의 모든 작은 개들이 다섯 번째 발가락을 발견하지 못했고 큰 개들의 50% 이상의 충격에서 더 많은 발가락을 발견하게 될 것이라는 놀라운 결론에 도달했다.
츠키노내 추측으로는, 그 사이즈를 바꾼 것 같아neighborhood
작은 개에게는 작은 것으로, 큰 개에게는 큰 것으로. ★★★★★★★★★★★★★★★★★.generate_binary_structure
을 사용법
그래서 혹시 발끝 크기에 맞는 발끝 면적 척도를 가지고 계신 분이 더 좋은 발끝 위치를 더 잘 알려주시면 감사하겠습니다.
로컬 최대 필터를 사용하여 피크를 감지했습니다.첫 번째 4개의 발 데이터 세트에 대한 결과는 다음과 같습니다.
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
마스크에서 모든 개별 객체에 레이블을 지정합니다.★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
백그라운드에서 노이즈가 발생하지 않기 때문에, 이 방법은 올바르게 동작합니다.이 경우 백그라운드에서 불필요한 피크가 많이 검출됩니다.또 다른 중요한 요소는 이웃의 크기이다.피크 사이즈가 변경되면 조정해야 합니다(는 거의 비례합니다).
솔루션
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개의 사례를 평가할 수 있다.
이것은 이미지 등록 문제입니다.일반적인 전략은 다음과 같습니다.
- 이미 알려진 예나 데이터에 대한 어떤 종류의 사전 사례를 가지고 있습니다.
- 데이터를 예제에 적합시키거나 예제를 데이터에 적합시킵니다.
- 처음부터 데이터가 대략적으로 정렬되어 있으면 도움이 됩니다.
"실효할 수 있는 가장 멍청한 방법"은 다음과 같습니다.
- 대략 예상하는 장소에서 다섯 개의 발가락 좌표부터 시작하세요.
- 각각에 대해 반복적으로 언덕 꼭대기로 올라갑니다.즉, 현재 위치가 주어진 경우, 값이 현재 픽셀보다 클 경우 최대 인접 픽셀로 이동합니다.발가락 좌표가 움직이지 않게 되면 멈추세요.
방향 문제를 해결하려면 기본 방향(North, North East 등)에 대해 8개 정도의 초기 설정을 할 수 있습니다.각 항목을 개별적으로 실행하고 두 개 이상의 발가락이 같은 픽셀에 도달하는 결과를 모두 폐기합니다.좀 더 생각해 보겠습니다만, 이러한 것은 아직 화상 처리에서 연구되고 있습니다.정답은 없습니다!
조금 더 복잡한 아이디어: (가중치) K-평균 클러스터링.그렇게 나쁘지 않아.
- 처음에는 5개의 토우 좌표로 시작했지만 지금은 "클러스터 중심"입니다.
그 후 컨버전스가 될 때까지 반복합니다.
- 각 픽셀을 가장 가까운 클러스터에 할당합니다(각 클러스터에 대한 목록을 작성하기만 하면 됩니다.
- 각 군집의 질량 중심을 계산합니다.각 클러스터에 대해 Sum(좌표 * 강도 값)/Sum(좌표)
- 각 클러스터를 새 질량 중심으로 이동하십시오.
이 방법을 사용하면 훨씬 더 나은 결과를 얻을 수 있으며, 발가락 식별에 도움이 될 수 있는 각 클러스터의 질량을 얻을 수 있습니다.
(앞에 클러스터 수를 지정했습니다.클러스터링을 사용하는 경우 밀도를 어떤 방법으로든 지정해야 합니다.이 경우 적절한 클러스터 수를 선택하거나 클러스터 반지름을 선택하여 최종 클러스터 수를 확인합니다.후자의 예로는 평균 시프트가 있습니다.
구현 세부사항 또는 기타 세부사항이 부족하여 죄송합니다.난 이걸 코드화하고 싶지만 마감일이 있어.다음 주까지 다른 방법이 없으면 알려주시면 시도해 보겠습니다.
영구 호몰로지를 사용하여 데이터 세트를 분석하면 다음과 같은 결과를 얻을 수 있습니다(클릭하여 확대).
이것은 이 SO 답변에 설명된 피크 검출 방법의 2D 버전입니다.위 그림은 단순히 지속성별로 정렬된 0차원 지속적 호몰로지 클래스를 보여줍니다.
scipy.misc.imerize()를 사용하여 원래 데이터 세트를 2배 업그레이드했습니다.단, 4개의 발을 1개의 데이터 세트로 간주하고 있기 때문에 4개로 분할하면 문제가 쉬워집니다.
방법론이 배경에는, 각 픽셀의 레벨을 할당하는 함수의 함수 그래프를 생각할 수 있습니다.다음과 같습니다.
이제 높이 255의 수위가 계속해서 낮은 수위로 내려가는 것을 생각해 봅시다.현지의 막시마의 섬에는 (탄생)이 뜬다.안장점에서는 두 섬이 합쳐진다; 우리는 낮은 섬이 높은 섬과 합쳐지는 것으로 본다(죽음).이른바 지속성 다이어그램(0차원의 호몰로지 클래스, 우리의 섬)은 모든 섬의 출생 가치에 대한 죽음을 나타낸다.
섬의 지속성은 출생 수준과 사망 수준의 차이입니다. 점이 회색 주 대각선으로 수직 거리입니다.이 그림은 지속성을 감소시켜 섬에 레이블을 표시합니다.
첫 번째 사진은 이 섬들의 출생지를 보여준다.이 방법은 국소적인 최대치를 제공할 뿐만 아니라 위에서 언급한 지속성으로 "중요도"를 수량화한다.그런 다음 너무 낮은 지속성으로 모든 섬을 걸러낼 것이다.그러나 이 예에서는 모든 섬(즉, 모든 로컬 최대값)이 찾는 피크가 됩니다.
Python 코드는 여기에서 찾을 수 있습니다.
이 문제는 물리학자들에 의해 어느 정도 깊이 연구되어 왔다.ROOT에는 적절한 구현이 있습니다.TSpectrum 클래스(특히 케이스의 경우는 TSpectrum2)와 그 메뉴얼을 참조해 주세요.
참고 자료:
- M. Morhac 등:다차원 일치 감마선 스펙트럼의 백그라운드 제거 방법.물리학 연구 A 401(1997년) 113-132.
- M. Morhac 등:효율적인 1차원 및 2차원 골드 디콘볼루션 및 감마선 스펙트럼 분해에 적용.물리학 연구 A 401(1997년) 385-408의 핵 계기와 방법.
- M. Morhac 등:다차원 일치 감마선 스펙트럼의 피크 식별.연구 물리학에서의 핵 기구 및 방법 A 443(2000), 108-125.
...NIM에 대한 서브스크립션에 액세스할 수 없는 경우:
지금쯤은 충분히 진행되겠지만 k-평균 클러스터링 방법을 사용할 것을 제안하지 않을 수 없습니다. k-평균은 감독되지 않은 클러스터링 알고리즘으로, 데이터를 (모든 수의 3D로) 가져가서 다른 경계를 가진 k개의 클러스터로 배열합니다.이 송곳니들이 발가락이 몇 개인지 정확히 알 수 있어서 좋네요.
게다가 Scipy에 실장되어 있어 매우 좋습니다(http://docs.scipy.org/doc/scipy/reference/cluster.vq.html)).
으로 해결하기 위해 할 수 다음 、 d: 、 3D 클 here 、 다 here 、 다 here 、 here here here here here here here 。
당신이 원하는 것은 조금 다르지만(2D, 압력값 포함) 그래도 시도해 볼 수 있을 것 같습니다.
다음은 이미지의 (이산) 라플라시안을 계산하는 방법입니다.오리지널 이미지보다 더 드라마틱한 maxima로 (네거티브하고) 클 것으로 예상합니다.따라서 maxima를 찾는 것이 더 쉬울 수 있습니다.
여기 또 다른 아이디어가 있습니다.고압 스팟의 일반적인 크기를 알고 있다면 먼저 같은 크기의 가우스를 사용하여 이미지를 부드럽게 만들 수 있습니다.이것에 의해, 간단하게 화상을 처리할 수 있습니다.
그냥 머릿속에서 몇 가지 생각이 떠올랐어요.
- 스캔의 그라데이션(비교적)을 취하여 잘못된 콜이 제거되는지 확인합니다.
- 국소 최대치를 취하다
OpenCV는 꽤 괜찮은 Python API를 갖추고 있어 유용한 기능을 갖추고 있습니다.
미가공 데이터 감사합니다.나는 전철을 타고 있는데 여기까지 왔다.당신의 txt 파일을 regexps로 마사지하고 시각화를 위해 javascript와 함께 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>
★★★★★★★★★★★★★★★★★★★:
되는 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)
입니다.X_i
,alfa
실험적으로 정점을 찍는 매개 변수입니다.
이제 메트로폴리스 헤이스팅스 마법을 부릴 차례입니다.
합니다.1 랜덤 마커를 선택하고 랜덤 방향으로 1픽셀 이동합니다.
한다.2 . dE、 ,e 、 ee 、 즉 2 、 2 2 2 2 2 2 2 2 2 2 2 2 。
.3. 0-1이라고 .
If 4. If 。dE<0
★★★★★★★★★★★★★★★★★」exp(-beta*dE)>r
1번으로 하다그렇지 않으면 이동을 취소하고 1로 이동합니다.
이것은 마커가 발바닥으로 수렴될 때까지 반복해야 한다.베타는 스캔을 제어하여 트레이드오프를 최적화하므로 실험적으로 최적화해야 합니다.또한 시뮬레이션 시간(시뮬레이션 어닐링)에 따라 지속적으로 증가할 수 있습니다.
훈련 데이터를 작성할 수 있다면 뉴럴 네트워크를 사용해 보는 것이 좋을지도 모릅니다.하지만 이것은 손으로 주석을 달아야 합니다.
을 수 것을 .maxima
:
from skimage.feature import peak_local_max
skimage "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
다음은 제가 대형 망원경에 비슷한 작업을 할 때 사용한 또 다른 접근법입니다.
1) 가장 높은 픽셀을 검색합니다.그런 다음 2x2에 가장 적합한 것을 검색하거나(아마도 2x2 합계를 최대화함), 가장 높은 픽셀을 중심으로 하는 4x4의 하위 영역 내에서 2d 가우스 적합을 수행합니다.
그런 다음 발견된 2x2 픽셀을 피크 중심 주위에 0(또는 3x3)으로 설정합니다.
1)로 돌아가서 최고 피크가 소음 임계값 아래로 떨어질 때까지 반복하거나 필요한 모든 발가락이 확보됩니다.
대략적인 윤곽...
연결된 성분 알고리즘을 사용하여 각 다리 부분을 분리하는 것이 좋습니다.Wiki 에서는, 다음의 URL 에 적절한 코드로 기재되어 있습니다.http://en.wikipedia.org/wiki/Connected_Component_Labeling
4와 8 중 어느 쪽을 사용할지 결정해야 합니다.개인적으로는 대부분의 문제에 대해 6-연결성을 선호합니다.어쨌든, 각각의 「인쇄」를 접속된 영역으로 분리하면, 그 영역을 반복해 최대치를 찾아낼 수 있을 만큼 충분히 간단할 것입니다.Maxima를 찾은 후에는 주어진 "토우"로 식별하기 위해 미리 정해진 임계값에 도달할 때까지 영역을 반복적으로 확대할 수 있습니다.
여기서 한 가지 미묘한 문제는 컴퓨터 비전 기술을 사용하여 오른쪽/왼쪽/앞쪽/뒤쪽 발가락을 보기 시작하면 회전, 기울기, 번역 등을 고려해야 한다는 것입니다.이것은 이른바 "추정"의 분석을 통해 달성된다.비전 어플리케이션에서는 고려해야 할 몇 가지 다른 순간이 있습니다.
중심 모멘트: 번역 불변 정규 모멘트: 스케일링 및 번역 불변 모멘트: 변환, 스케일, 회전 불변
모멘트에 대한 자세한 내용은 Wiki에서 "이미지 모멘트"를 검색하여 확인할 수 있습니다.
아마도 당신은 가우스 혼합 모형과 같은 것을 사용할 수 있습니다.여기 GMM을 실행하기 위한 Python 패키지가 있습니다(Google 검색을 방금 했습니다). http://www.ar.media.kyoto-u.ac.jp/members/david/softwares/em/
흥미로운 문제네요제가 시도하고 싶은 해결책은 다음과 같습니다.
2D 가우스 마스크를 사용한 컨볼루션과 같은 로우패스 필터를 적용합니다.이것에 의해, 다수의 값(아마도 부동 소수점이라고는 할 수 없습니다)을 얻을 수 있습니다.
각 패드(또는 토우)의 알려진 대략적인 반지름을 사용하여 2D 비최대 억제를 수행하십시오.
이렇게 하면 서로 가까운 여러 후보자를 두지 않고도 최대한의 포지션을 얻을 수 있습니다.명확하게 하기 위해 스텝1의 마스크 반지름은 스텝2에서 사용한 반지름과 비슷해야 합니다.이 반경은 선택 가능하거나 수의사가 사전에 명시적으로 측정할 수 있습니다(연령/종 등에 따라 다릅니다).
제안된 솔루션 중 일부(평균 이동, 신경망 등)는 어느 정도 효과가 있을 수 있지만 지나치게 복잡하여 이상적이지 않을 수 있습니다.
jetxee의 알고리즘을 사용하면 속임수를 쓸 수 있을 것 같아요.그는 처음 세 개의 발가락을 발견했고, 당신은 그것을 바탕으로 네 번째 발가락이 어디에 있는지 추측할 수 있을 것이다.
여기 간단한 코드가 있습니다만, 이 정도의 데이터 세트라면 문제 없습니다.
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 정사각형 두 개가 있습니다(그리고 두 개의 합은 서로 동일).그 중 하나는 2x2 정사각형에서 하나의 정사각형을 선택하지만 다른 하나는 왼쪽으로 치우쳐 있습니다.다행히도, 우리는 여러분이 원하는 것을 더 많이 고르는 것을 볼 수 있지만, 이것은 여러분이 실제로 원하는 것을 얻기 위해 항상 다른 아이디어를 사용해야 할 수도 있습니다.
이 질문에 대한 답은 모르겠지만 네이버가 없는 n개의 최고봉만 찾으면 될 것 같습니다.
요점은 이렇다.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
평면에 있는 모든 2x2 정사각형 목록을 작성하고 합계를 기준으로 정렬합니다(내림차순).
먼저 가장 높은 값의 정사각형을 "paw list"로 선택합니다.그런 다음 이전에 찾은 정사각형과 교차하지 않는 차선의 정사각형 중 4개를 반복적으로 선택합니다.
단계별로 진행하면 어떻게 됩니까?먼저 글로벌 최대값을 찾고 필요한 경우 주변 포인트를 지정한 값에 따라 처리한 후 발견된 영역을 0으로 설정하고 다음 영역에 대해 반복합니다.
언급URL : https://stackoverflow.com/questions/3684484/peak-detection-in-a-2d-array
'IT' 카테고리의 다른 글
javax.servlet 가져오기를 확인할 수 없습니다. (0) | 2022.12.27 |
---|---|
단일 스테이트먼트에서 Java로 실행된 여러 쿼리 (0) | 2022.12.27 |
플레인 오브젝트를 ES6 맵으로 변환하는 방법 (0) | 2022.12.27 |
npm 사용자가 설치한 패키지를 나열하는 방법 (0) | 2022.12.07 |
Jinja2 단축형 조건어 (0) | 2022.12.07 |