Showing posts with label tips. Show all posts
Showing posts with label tips. Show all posts

Friday, July 17, 2020

การหา local maxima และ minima อย่างรวดเร็ว

สมมติว่าเรามีสัญญาณหนึ่ง แล้วเราต้องการหาว่าจุดยอดอยู่ที่ไหน คำสั่งใน MATLAB ที่ใช้เป็นปกติคือ findpeaks แต่ถ้าใครเคยใช้คำสั่งนี้ใน loop จะเห็นว่ามันช้ามาก ดังนั้นสำหรับฟังชั่นที่ไม่มีสัญญาณรบกวน มันมีวิธีอื่นที่ง่ายและเร็วกว่า วันนี้จะมาแสดงวิธีให้ดู

ก่อนอื่น สมมติเรามี sinc function signal ละกัน

x = linspace(-10,10,501);
y = sinc(x);
เราสามารถหาความชันของสัญญาณด้วยคำสั่ง diff

A = diff(y);
เมื่อเทียบกันสัญญาณรูปบน จะเห็นว่าจุดสูงสุดของสัญญาณคือจุดที่ค่าควาามชันเปลี่ยนจาก + เป็น - และจุดต่ำสุดของสัญญาณคือจุดที่ความชันเปลี่ยนจาก - เป็น + เพราะว่าเราสนใจแค่เครื่องหมาย เราจึงเปลี่ยนค่าความชันเป็นเครื่อง + หรือ - ด้วยคำสั่ง sign

A = sign(A)
หลังจากนั้นเราจะหาตำแหน่งที่สัญญาณเปลี่ยนเครื่องหมายจาก + เป็น -  และ - เป็น + ด้วยคำสั่ง conv


A = conv(A,[-1,1]);
ทีนี้เราก็จะหาจุดสูงสุดได้เมื่อ A = 2 และ จุดต่ำสุดที่ A = -2

maximas = find(A == 2);
minimas = find(A == -2);

เพื่อความกระชับ เราสามารถเขียนโค้ดทั้งหมดได้ในบรรทัดเดียวดังนี้

maximas = find(conv(sign(diff(y)),[-1,1]) == 2);
minimas = find(conv(sign(diff(y)),[-1,1]) == -2);

เพื่อยืนยันว่ามันใช้ได้เดี๋ยวจะขอพล๊อตกราฟให้ดู ดังนี้

x = linspace(-10,10,501);
y = sinc(x);
ymax = NaN(length(y));
ymin = ymax;
maximas = find(conv(sign(diff(y)),[-1,1]) == 2);
minimas = find(conv(sign(diff(y)),[-1,1]) == -2);
ymax(maximas) = y(maximas);
ymin(minimas) = y(minimas);
plot(x,y,'-b','LineWidth',2);hold on;
plot(x,ymax,'*r','LineWidth',2);
plot(x,ymin,'or','LineWidth',2);
set(gca,'FontSize',16);
hold off;