Python - Signal Recovery

以前在做天空偵測的時候也類似目前的 case,也就是呢,我們要先分析客戶給的信號圖,在進行必要的裁剪、銳化細節、canny 邊緣檢測,在跟據最後 canny 的圖將信號畫好,(至於說為啥我要做那些步驟,阿就試出來的,我最愛做的就是 try error 這種繁瑣的事情)

設計流程

以這張圖為例,我們可以看到上下方約 1/3 都是我們不需要的東西,所以我們進行 crop image 的動作 。
再來就是那些該死的示波器背景,等等我們就用 blur 把它濾掉,因為輸入屬於中型圖片,所以 blur 我們使用[5,5]的強度。

後面畫細節是由上到下,取最高最低兩個點,如果沒有發現像素點就會沿用前一條線高低點。當然這還是有改善空間,模糊不知道用高斯模糊效果好不好,還有很多可以試試看。但因為這件事貌似沒那麼急,就暫時先告一段落,如果有後續發展,會再繼續更新本篇。

調整出來步驟為

  • step1: crop image 裁剪原圖
  • step2: floodfill image 嘗試塗掉背景 <== 強度應該可以再調整
  • step3: kernel image 銳化留下來的部分,’[[0, -1, 0], [-1, 5, -1], [0, -1, 0]’
  • step4: blur image 抹掉細節(模糊),’[5,5]’ <== 或許可以用高斯模糊
  • step5: canny image 100,200 邊緣檢測 <== sobel 展現的效果不好,所以還是用canny
  • step6: result image 畫線

0QD8imz4.png
original(已移除)

(20200702移除)

canny
2

result
3


folder Tree

$tree
D:.
└─gw_signal_recovery
    ├─input
    ├─output
    └─tmp

code

from os.path import isfile, join
from os import listdir
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
from PIL import ImageFilter

import cv2   # if not found,try pip install opencv-python
import os

print("Change the current working directory to path:", os.path.dirname(__file__))
os.chdir(os.path.dirname(__file__))

onlyfiles = [f for f in listdir("./input") if isfile(join("./input", f))]

print(onlyfiles)
'''
3YljKfLQ.png
4B2Dcn2o.png
8dJosPug.png
8uS7qspI.png
buY6cs6U.png
Clqh9OD0.png
DH1QeME4.png
jyicdNJM.png
KsJUDLN0.png
m-GNRpbw.png
TO5-rs9o.png
u4J8dZ7o.png
VvCGeC4o.png
'''

# 將波形以外的背景填成白色


def floodfill_image(image, power):
    copyImage = image.copy()  # 複製原圖像
    h, w = image.shape[:2]  # 讀取圖像的寬和高
    mask = np.zeros([h+2, w+2], np.uint8)  # 新建圖像矩陣 +2是官方函數要求

    cv2.floodFill(copyImage, mask, (517, 260), (255, 255, 255), (power,
                                                                 power, power), (power, power, power), cv2.FLOODFILL_FIXED_RANGE)
    #cv.imshow("floodFill", copyImage)
    return copyImage

# 將canny最後結果填上白色


def result_image(image):
    copyImage = image.copy()
    rows, cols = copyImage.shape
    tmp_top = 0
    tmp_down = 0
    # 圖片大小
    # print(str(rows),",",str(cols))
    for i in range(cols):
        top = 0
        down = rows
        for j in range(rows):
            k = copyImage[j, i]
            if(k > 100):
                if (j > top):
                    top = j
                if (j < down):
                    down = j
        if(down - top > rows/2):
            cv2.line(copyImage, (i, tmp_top),
                     (i, tmp_down), (255, 255, 255), 1)
            #print("top =" + str(tmp_top) +",down ="+str(tmp_down))

        else:
            cv2.line(copyImage, (i, top), (i, down), (255, 255, 255), 1)
            tmp_top = top
            tmp_down = down

    return copyImage


def cv2_show_img(title, img, is_save):
    cv2.imshow(title, img)
    if(is_save):
        cv2.imwrite("output\\" + title, img)


index = 0 #方便檔案總管排序
# === main ===
for file in onlyfiles:
    src = cv2.imread("input\\" + file)
    H, W, channels = src.shape

    # 裁切區域的 x 與 y 座標(左上角)
    x = 10
    y = 90

    # (右下角)
    x1 = W-30
    y1 = 545
    crop_img = src[y:y1, x:x1]
    cv2_show_img(str(index) + "_1_original_" + file , src, True)

    #cv2.imshow("crop_img", crop_img)

    # flood fill 邊緣偵測
    ff_img = floodfill_image(crop_img, 35)
    #cv2.imshow("floodfill", ff_img)

    # blur 模糊
    blur = cv2.blur(ff_img, (5, 5))  # 中型圖片
    #cv2.imshow("blur", blur)

    # kernel 銳化
    kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]], np.float32)
    kernel_img = cv2.filter2D(blur, -1, kernel=kernel)
    #cv2.imshow("kernel", kernel_img)

    # canny 邊緣偵測
    canny = cv2.Canny(kernel_img, 100, 200)
    cv2_show_img(str(index) + "_2_canny_" + file, canny, True)

    # sobel 邊緣偵測(未使用)
    '''
    Gx = cv2.Sobel(blur,cv2cv.CV_16S,1,0)
    Gy = cv2.Sobel(blur,cv2.CV_16S,0,1)

    absX = cv2.convertScaleAbs(Gx)
    absY = cv2.convertScaleAbs(Gy)

    dst = cv2.addWeighted(absX,0.5,absY,0.5,0)

    cv2.imshow("absX", absX)
    cv2.imshow("absY", absY)
    cv2.imshow("sobel", dst)
    '''

    result_img = result_image(canny)
    cv2_show_img(str(index) + "_3_result_" + file, result_img, True)

    # 按任一鍵繼續下一張
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    index += 1

Result

3YljKfLQ.png
5
6


4B2Dcn2o.png
8
9


8dJosPug.png
11
12


8uS7qspI.png
14
15


buY6cs6U.png
17
18


Clqh9OD0.png
20
21


DH1QeME4.png
23
24


jyicdNJM.png
26
27


KsJUDLN0.png
29
30


m-GNRpbw.png
32
33


TO5-rs9o.png
35
36


u4J8dZ7o.png
38
39


VvCGeC4o.png
14
15



  轉載請註明: YuYan's blog Python - Signal Recovery

  目錄