2011-11-27 157 views
0

我有相似的正和負值的測量數據,其應該是這樣的:消除噪聲/尖峯

ReqData=[0 0 -2 -2 -2 -2 -2 -2 0 0 0 -2 -2 -2 -2 0 0 2 2 2 2 2 2 0 0 2 2 2 2 2 0 0 2 2 2 2 2 0 0 2 2 2 0 0]' 

然而,存在的一些數據測量噪聲 - 所以真正的數據是這樣的:

RealData=[0 0 -2 -2 -2 -2 -2 -2 0 0 0 -2 -2 -2 -2 0 0 2 2 2 2 -4 -1 0 0 2 2 2 2 -7 0 0 2 2 2 2 -1 0 0 2 2 2 0 0]' 
  1. 我如何從RealData去除噪音底,並用Matlab將其轉換成ReqData
  2. 我如何找到每組正面或負面數據的開始和停止索引,並使用Matlab分割它們?例如,ansPositive = [3,8, 12, 15]'ansNegative = [18, 23, 26, 30, 33, 37, 40, 42]'

回答

1

正如你給我寄了另一個數據集是從你這裏張貼了一個完全不同的,我會解釋另一種方法來處理你的數據。

爲了完整起見,你可以找到數據,如下圖設置的一個細節:

New dataset

在左側你可以看到完整的數據集,而右邊是一個細節。與之前的數據集相比,我們發現每個峯都不是恆定的水平,我們也不需要像以前那樣以最近鄰居的方式進行插值。

首先,我以前的答案在整個數據集上運行得非常慢(我的部分編碼很差),但它很可能工作不好,因爲所有峯值可能不會被投影到正確的值(例如,圖像最常用的值是4,4.1和0(其次是-4.05和其他))。這會導致我以前的算法失敗。爲了規避這個問題,選擇兩個閾值水平是我們構建預測變量的一個很容易的事情:大於正閾值的東西被認爲是恆定正值,小於負閾值的東西被認爲是負常數,在之間被認爲是零。

通過選擇體面的閾值,可以得到相當強大的重建: Reconstructed signal

你可以看到綠色的重建,而閾值顯示爲紅色虛線線。應該可以根據實際數據自動選擇這些閾值;但是我把它留給你(看看我以前的代碼,以瞭解你如何解決這個問題)。

相應的源代碼:

thresholdNeg = -3; 
idxNeg = RealData<thresholdNeg; 
valueNeg = mean(RealData(idxNeg)); 

thresholdPos = 3; 
idxPos = RealData>thresholdPos; 
valuePos = mean(RealData(idxPos)); 

reconData   = zeros(size(RealData)); 
reconData(idxPos) = valuePos; 
reconData(idxNeg) = valueNeg; 

n = numel(reconData); 

plot(RealData,'b'); hold on; 
plot(reconData,'-gx'); 
plot([1 n NaN n 1],[thresholdPos thresholdPos NaN thresholdNeg thresholdNeg], 'r--'); 

編輯: 如果你想,如果你放大近似恆定的水平,以保持包含在高和低的水平信號(的任何信息,可以注意到另一個信號的存在),則可以使用反向閾值技術:將信號保留在任何地方,但將信號置於0,其中信號在閾值之間。

+0

Great Egon!奇蹟般有效 !你讓我今天一整天都感覺很好 !太感謝了 ! – tgv

0

這取決於你的RealData有多嘈雜,這裏有點混亂。例如RealData(16)是負數,但ReqData(16)是正數,那麼在這種情況下你想要什麼輸出?

我會做:

RealDataPos=double(RealData'>0); 
RealDataPosBeginning=find(conv(RealDataPos,[-1 1 0],'same')>0); 
RealDataPosEnd=find(conv(RealDataPos,[0 1 -1],'same')>0); 

RealDataNeg=double(RealData'<0); 
RealDataNegBeginning=find(conv(RealDataNeg,[-1 1 0],'same')>0); 
RealDataNegEnd=find(conv(RealDataNeg,[0 1 -1],'same')>0); 

PS:評論,如果你想要的東西更復雜,處理的某個時候正序的reaData的EN變爲負的事實。

+0

嗨,奧利! RealData(16)和ReqData(16)都是0.無論如何,重點是,我想在要修正的脈衝結束時刪除尖峯。 – tgv

0

您可以使用類似下面的代碼來重建您的數據。

它將首先確定最頻繁發生的振幅。它假定3個最頻繁的幅度是正確的,你總是可以施加稍微不同的約束(例如檢查它們中的兩個是否具有相同的絕對值並且總是包括)。

然後它找到信號具有不同幅度的採樣點並將其校正爲信號的先前幅度。

clc; clear all; close all; 

ReqData=[0 0 -2 -2 -2 -2 -2 -2 0 0 0 -2 -2 -2 -2 0 0 2 2 2 2 2 2 0 0 2 2 2 2 2 0 0 2 2 2 2 2 0 0 2 2 2 0 0]'; 
RealData=[0 0 -2 -2 -2 -2 -2 -2 0 0 0 -2 -2 -2 -2 0 0 2 2 2 2 -4 -1 0 0 2 2 2 2 -7 0 0 2 2 2 2 -1 0 0 2 2 2 0 0]'; 

ReconData = RealData; 

amplitudes = unique(RealData); 
histogram = hist(RealData,amplitudes); 
[histogram, sorted] = sort(histogram); 
amplitudes = amplitudes(sorted); 

allowedValues = amplitudes(end-2:end); 
%allowedValues = [-1 0 1] * 2; 

spikes = find(arrayfun(@(x) (~ismember(x,allowedValues)),RealData)); 
for iSpike = 1:numel(spikes) 
    jSpike = spikes(iSpike); 
    ReconData(jSpike) = ReconData(jSpike-1); 
end 

plot(ReqData,'-or'); hold on; 
plot(RealData,'b'); 
plot(ReconData,'-gx'); 
+0

謝謝Egon!看起來很好的示例數據顯示。但是,對實際文件(11MB)給出錯誤:嘗試訪問ReconData(0);索引必須是正整數或邏輯。 錯誤(行20) ReconData(jSpike)= ReconData(jSpike-1); – tgv

+0

@tgv:表示第一個樣本不是可接受的值。你總是可以對這種情況進行明確的檢查,將其置於零或你喜歡的任何值。 – Egon