[Python] OpenCV 彩色轉灰階(RGB to Gray)

第一種方式:

import cv2

image = cv2.imread(‘test.jpg’) #讀取影像

image_g = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) #透過轉換函式轉為灰階影像

cv2.imwrite(‘test_g.jpg’, image_g) #儲存影像

第二種方式:

import cv2

image_g = cv2.imread(‘test.jpg’, 0) #直接以灰階方式讀取影像

cv2.imwrite(‘test_g.jpg’, image_g) #儲存影像

img = cv2.imread('gray.jpg',0)

0 for gray and 1 for color


cv2.imread load an image with three channels unless CV_LOAD_IMAGE_GRAYSCALE is set.

>>> import cv2
>>> image = cv2.imread('foo.jpg')
>>> print image.shape
 (184, 300, 3)
>>> gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
>>> print gray_image.shape 
 (184, 300)
>>> cv2.imwrite('gray.jpg', gray_image)

opencv python 影像模糊與反鋸齒處理

很實用的技能,建議學起來。一行指令就搞定了。好強的 OpenCV

如果還沒有安裝opencv 請服用下面的指令:

python3 -m pip install opencv-python

影象平滑技術如高斯模糊,Median模糊等,模糊真的很好用,因為模糊捨棄了「細節」,再結合二值化(Image Thresholding),就可以讓原有的資訊變的更圓潤和飽滿,可以做出反鋸齒(Anti-aliasing)的效果。

OpenCV 的平滑模糊化技術:

  • 平均濾波 Averaging:使用 opencv 的 cv2.blur 或 cv2.boxFilter
  • 高斯濾波 Gaussian Filtering:使用 opencv 的 cv2.GaussianBlur
  • 中值濾波 Median Filtering:使用 opencv 的 cv2.medianBlur
  • 雙邊濾波 Bilateral Filtering:使用 opencv 的 cv2.bilateralFilter

使用範例:

import cv2
import numpy as np
img = cv2.imread('opencv-logo-white.png')
blur = cv2.blur(img,(5,5))

二值化

影像二值化簡單的方法,如果像素值pixel大於門檻值threshold,就指定一個新數值(例如白色),否則就指定另一個新數值(例如黑色),
這邊使用 opencv 的 cv2.threshold,第一個參數來源需要是灰階影像,第二個參數是用來對像素值進行分類的門檻值,第三個參數為最大灰階值,第四個參數為二值化的類型如下所示:
cv2.THRESH_BINARY:Threshold Binary,即二值化,將大於門檻值的灰階值設為最大灰階值,小於門檻值的值設為0。
cv2.THRESH_BINARY_INV:Threshold Binary, Inverted,將大於門檻值的灰階值設為0,其他值設為最大灰階值。
cv2.THRESH_TRUNC:Truncate,將大於門檻值的灰階值設為門檻值,小於門檻值的值保持不變。
cv2.THRESH_TOZERO:Threshold to Zero,將小於門檻值的灰階值設為0,大於門檻值的值保持不變。
cv2.THRESH_TOZERO_INV:Threshold to Zero, Inverted,將大於門檻值的灰階值設為0,小於門檻值的值保持不變。

使用範例:

import cv2
import numpy as np
img = cv2.imread('your-image.png', 0)
ret, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)

執行結果

1:使用 Blur + threshold

右邊是原圖,右邊是套用效果後。

2:使用 GaussianBlur + threshold

右邊是原圖,右邊是套用效果後。

3:使用 medianBlur + threshold

右邊是原圖,右邊是套用效果後。

心得,使用起來差異不會很大,但Blur 可以調的模糊程度會較高,較大的筆觸會造成較嚴重的暈染效果,還有筆畫相連。先降噪,blur ,再降噪,再取二值化,這些步驟重覆並交叉套用,效果也很好!


相關文章

Smoothing Images
https://docs.opencv.org/4.5.2/d4/d13/tutorial_py_filtering.html

影像平滑模糊化 blur
https://shengyu7697.github.io/python-opencv-blur/

影像二值化 Image Thresholding
https://shengyu7697.github.io/python-opencv-threshold/

opencv python 影像去噪
https://stackoverflow.max-everyday.com/2021/07/opencv-python-image-denoise/

opencv python 影像去噪

很實用的技能,建議學起來。一行指令就搞定了。好強的 OpenCV

如果還沒有安裝opencv 請服用下面的指令:

python3 -m pip install opencv-python

OpenCV提供了這種技術的四種變體。

  • cv2.fastNlMeansDenoising() – 使用單個灰度影象
  • cv2.fastNlMeansDenoisingColored() – 使用彩色影象。
  • cv2.fastNlMeansDenoisingMulti() – 用於在短時間內捕獲的影象序列(灰度影象)
  • cv2.fastNlMeansDenoisingColoredMulti() – 與上面相同,但用於彩色影象。

參數:

  1. h:引數決定濾波器強度。較高的h值可以更好地消除噪聲,但也會刪除影象的細節 (10 is ok)
  2. hForColorComponents:與h相同,但僅適用於彩色影象。 (通常與h相同)
  3. templateWindowSize:應該是奇數。 (recommended 7)
  4. searchWindowSize:應該是奇數。 (recommended 21)

使用範例:

import numpy as np
import cv2 as cv
img = cv.imread('die.png')
dst = cv.fastNlMeansDenoisingColored(img,None,10,10,7,21)

如上所述,它用於從彩色影象中去除噪聲。


相關文章

Image Denoising
https://docs.opencv.org/3.4/d5/d69/tutorial_py_non_local_means.html

[Python] 圖片降噪

圖片驗證碼識別的可以分為幾個步驟,一般用 Pillow 庫或 OpenCV 來實現,取得圖片驗證碼文字的處理流程:

  • 1.灰度處理&二值化
  • 2.降噪
    所謂降噪就是把不需要的信息通通去除,比如背景,干擾線,干擾像素等等,只留下需要識別的字符,讓圖片變成2進制點陣,方便代入模型訓練。
  • 3.字符分割
  • 4.標準化
  • 5.識別 (OCR)

參考了這部教學影片:
[爬蟲實戰] 如何破解高鐵驗證碼 (1) – 去除圖片噪音點?
https://www.youtube.com/watch?v=6HGbKdB4kVY


python 用pip安装 cv2:

pip install opencv-python

說明:macOS 預設 python2 裡 numpy 的版本 numpy-1.8.0rc1,但 opencv 需要 1.11.1 以上,所以會安裝失敗,顯示:

ERROR: Cannot uninstall 'numpy'. It is a distutils installed project and thus we cannot accurately determine which files belong to it which would lead to only a partial uninstall.

解法:

sudo python -m pip install numpy –ignore-installed numpy
sudo python -m pip install opencv-python

python 用pip安装 matplotlib:

pip install matplotlib

python 用pip安装 pytesseract:

pip install pytesseract

Tesseract OCR 安裝方法:
https://github.com/tesseract-ocr/tesseract/wiki


透過 selenium 的 element.screenshot() 即可取得驗證碼圖片:
https://selenium-python-zh.readthedocs.io/en/latest/api.html?highlight=screenshot#selenium.webdriver.remote.webelement.WebElement.screenshot

screenshot(filename)Saves a screenshot of the current element to a PNG image file. ReturnsFalse if there is any IOError, else returns True. Use full paths in your filename.

Args:filename: The full path you wish to save your screenshot to. This should end with a .png extension.
Usage:element.screenshot(‘/Screenshots/foo.png’)

Max取得到 screenshot:

透過下面的python程式:

from PIL import Image,ImageDraw
image = Image.open("captcha.png").convert("L")

取得convert 為灰階後影像檔:

透過下面程式,用來2分化影像:

def binarizing(img,threshold): #input: gray image
     pixdata = img.load()
     w, h = img.size
     for y in range(h):
       for x in range(w):
           if pixdata[x, y] < threshold:
               pixdata[x, y] = 0
           else:
               pixdata[x, y] = 255
     return img

降噪方案1:(不好用)

def depoint(img):   #input: gray image
     pixdata = img.load()
     w,h = img.size
     for y in range(1,h-1):
         for x in range(1,w-1):
             count = 0
             if pixdata[x,y-1] > 245:
                 count = count + 1
             if pixdata[x,y+1] > 245:
                 count = count + 1
             if pixdata[x-1,y] > 245:
                 count = count + 1
             if pixdata[x+1,y] > 245:
                 count = count + 1
             if count > 2:
                 pixdata[x,y] = 255
     return img

似乎只有使用 上/下/左/右 4個方向 shift 1點來判斷,如果遇到較大的噪會無效,處理結果:

效果似乎接近無效,因為黑點都略大。

改服用下面的程式碼:

#二值判断,如果确认是噪声,用改点的上面一个点的灰度进行替换
#该函数也可以改成RGB判断的,具体看需求如何
def getPixel(image,x,y,G,N):
    L = image.getpixel((x,y))
    if L > G:
        L = True
    else:
        L = False
 
    nearDots = 0
    if L == (image.getpixel((x - 1,y - 1)) > G):
        nearDots += 1
    if L == (image.getpixel((x - 1,y)) > G):
        nearDots += 1
    if L == (image.getpixel((x - 1,y + 1)) > G):
        nearDots += 1
    if L == (image.getpixel((x,y - 1)) > G):
        nearDots += 1
    if L == (image.getpixel((x,y + 1)) > G):
        nearDots += 1
    if L == (image.getpixel((x + 1,y - 1)) > G):
        nearDots += 1
    if L == (image.getpixel((x + 1,y)) > G):
        nearDots += 1
    if L == (image.getpixel((x + 1,y + 1)) > G):
        nearDots += 1
 
    if nearDots < N:
        return image.getpixel((x,y-1))
    else:
        return None
 
# 降噪 
# 根据一个点A的RGB值,与周围的8个点的RBG值比较,设定一个值N(0 <N <8),当A的RGB值与周围8个点的RGB相等数小于N时,此点为噪点 
# G: Integer 图像二值化阀值 
# N: Integer 降噪率 0 <N <8 
# Z: Integer 降噪次数 
# 输出 
#  0:降噪成功 
#  1:降噪失败 
def clearNoise(image,G,N,Z):
    draw = ImageDraw.Draw(image)
 
    for i in range(0,Z):
        for x in range(1,image.size[0] - 1):
            for y in range(1,image.size[1] - 1):
                color = getPixel(image,x,y,G,N)
                if color != None:
                    draw.point((x,y),color)

    image.save("test4_clearNoise.jpg")


image = Image.open("captcha.png").convert("L")
image_binary = binarizing(image, 180)
clearNoise(image_binary,50,4,6)

結果是有比較好:

但上面的圖片,還是「無法」使用pytesseract 進行OCR 辨視成功:

code = pytesseract.image_to_string(image_binary, config='digits')
print("code:", code)

改用OpenCV 看看,OpenCV提供了這種技術的四種去噪方法:
https://docs.opencv.org/3.0-beta/modules/photo/doc/denoising.html

  • cv2.fastNlMeansDenoising() – 使用單個灰度影象
  • cv2.fastNlMeansDenoisingColored() – 使用彩色影象。
  • cv2.fastNlMeansDenoisingMulti() – 用於在短時間內捕獲的影象序列(灰度影象)
  • cv2.fastNlMeansDenoisingColoredMulti() – 與上面相同,但用於彩色影象。

基本的 opencv 使用範例:

import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('die.png')
dst = cv2.fastNlMeansDenoisingColored(img,None,10,10,7,21)
plt.subplot(121),plt.imshow(img)
plt.subplot(122),plt.imshow(dst)
plt.show()

總結

Tesseract-ORC 對於這種弱驗證碼識別率還是可以,大部分字符能夠正確識別出來。只不過有時候會將數字 8 識別為 0。如果圖片驗證碼稍微變得復雜點,識別率大大降低,會經常識別不出來的情況。

如果想要做到識別率較高,那麽需要使用 CNN (Convolutional Neural Network,卷積神經網絡)或者 RNN (Recurrent Neural Network,循環神經網絡)訓練出自己的識別庫。正好機器學習很流行,學習一下也無妨。


卷積神經網路(Convolutional Neural Network, CNN)

CNN 也是模仿人類大腦的認知方式,譬如我們辨識一個圖像,會先注意到顏色鮮明的點、線、面,之後將它們構成一個個不同的形狀(眼睛、鼻子、嘴巴…),這種抽象化的過程就是CNN演算法建立模型的方式。卷積層(Convolution Layer) 就是由點的比對轉成局部的比對,透過一塊塊的特徵研判,逐步堆疊綜合比對結果,就可以得到比較好的辨識結果,過程如下圖。

卷積層(Convolution Layer)

如何從點轉成面呢? 就是以圖像的每一點為中心,取周遭 N x N 格的點構成一個面(N 稱為 Kernel Size,N x N 的矩陣權重稱為『卷積核』),每一格給予不同的權重,計算加權總和,當作這一點的 output,再移動至下一點以相同方式處理,至圖像的最後一點為止,這就是 CNN 的卷積層(Convolution Layer)。

相關文章:CS231n: Convolutional Neural Networks for Visual Recognition 
http://cs231n.github.io/convolutional-networks/
上面文章的「Convolution Demo」段落,它以動畫的方式說明取樣的方式,有助於更容易了解其原理。

卷積層處理方式與影像處理方法類似,採用滑動視窗(Sliding Window)運算,藉由給予『卷積核』不同的權重組合,就可以偵測形狀的邊、角,也有去除噪音(Noise)及銳化(Sharpen)的效果,萃取這些特徵當作辨識的依據,這也克服了迴歸(Regression)會受『異常點』(Outliers)嚴重影響推測結果的缺點。

資料來源:
Day 06:處理影像的利器 — 卷積神經網路(Convolutional Neural Network)
https://ithelp.ithome.com.tw/articles/10191820


循環神經網路(Recurrent Neural Network, RNN)

語言通常要考慮前言後語,以免斷章取義,也就是說,建立語言的相關模型,如果能額外考慮上下文的關係,準確率就會顯著提高,因此,學者提出『循環神經網路』(Recurrent Neural Network, RNN)演算法,它是『自然語言處理』領域最常使用的 Neural Network 模型。


相關文章:

速記AI課程-深度學習入門(二)
https://medium.com/@baubibi/%E9%80%9F%E8%A8%98ai%E8%AA%B2%E7%A8%8B-%E6%B7%B1%E5%BA%A6%E5%AD%B8%E7%BF%92%E5%85%A5%E9%96%80-%E4%BA%8C-954b0e473d7f

我發現,網路上很多AI相關的「入門」等級的教學文章,還滿容易懂和實作的。


相關影片:

1:[爬蟲實戰] 如何使用Selenium 抓取驗證碼?
https://www.youtube.com/watch?v=hF-dJj559ug

2:[爬蟲實戰] 如何破解高鐵驗證碼 (1) – 去除圖片噪音點?
https://www.youtube.com/watch?v=6HGbKdB4kVY

3:[爬蟲實戰] 如何破解高鐵驗證碼 (2) – 使用迴歸方法去除多餘弧線?
https://www.youtube.com/watch?v=4DHcOPSfC4c

上面影片的原始碼:
實作基於CNN的台鐵訂票驗證碼辨識以及透過模仿及資料增強的訓練集產生器 (Simple captcha solver based on CNN and a training set generator by imitating the style of captcha and data augmentation)
https://github.com/JasonLiTW/simple-railway-captcha-solver