つれづれなる備忘録

日々の発見をあるがままに綴る

ブログデザイン備忘録 ~ サーチコンソールのCLS問題(PC)、検証結果2

前回サーチコンソールのCSL問題の検証で不良(CLSが0.25以上)については合格で、改善必要については検証中になっていた。

atatat.hatenablog.com

前回の3/18時点でCLSが0.1以上のURL数が195ページあったが、下図のように現在では28ページまで減少した。さらに残る28件もCLSが0.11なので、もう一度検証を行ってフィールドデータ(閲覧数)を集めれば恐らく要改善のページが0になると考えられる。

"4/7時点のCSL検証経過"
4/7時点のCSL検証経過

ということで、サーチコンソールから再度検証を開始してみたので、検証結果がでたら報告しようと思う。

OpenCVの使い方9 ~ 台形補正2

 前回のOpenCVの台形補正で、変換座標を自動的に抽出して台形補正処理を行う方法について紹介する。前回は台形補正する領域の4点座標をペイントなどで見つけていたが、今回は輪郭抽出を用いることで画像から自動的に座標を抽出する。

1. 画像読み込みから輪郭抽出まで

 今回はネット上の名刺のサンプル画像の台形補正処理を試す。画像を読み込んだ後は以前紹介した2値化処理を行った後で輪郭抽出を実行する。

atatat.hatenablog.com

サンプル画像読み込み

import cv2
import numpy as np
from matplotlib import pyplot as plt
from google.colab import files
uploaded_file = files.upload()
uploaded_file_name = next(iter(uploaded_file))
orig = cv2.imread(uploaded_file_name)
src = cv2.cvtColor(orig, cv2.COLOR_BGR2RGB)
plt.imshow(src)

"テスト名刺画像"
テスト名刺画像

上記のテスト画像を以下の処理で2値化画像に変換する。

ret,th1 = cv2.threshold(gray,230,255,cv2.THRESH_BINARY)
plt.imshow(th1,cmap='gray',vmin = 0, vmax = 255)

"2値化処理画像"
2値化処理画像

2値化画像を用いて輪郭抽出処理を行う。輪郭抽出処理の詳細は今後別途記事にする予定だが、コードとしては以下を参考にしている。

qiita.com

まず輪郭を抽出するにはcv2.findContours()を用いて輪郭の座標を取得する。なおcv2.findContours()の引数の意味や種類は オブジェクト輪郭検出 | OpenCV / findContours を使用して画像中のオブジェクトの輪郭を検出する方法などを参照。

上記のコードでOpenCVのVer4.1以上では仕様の変更があり以下の部分のコードを用いた。(python - OpenCV version 4.1.0 drawContours - Stack Overflow)

tmp= cv2.findContours(th1, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours = tmp[0] if len(tmp) == 2 else tmp[1]

cv2.CHAIN_APPROX_SIMPLEと指定すると輪郭点のみに省略され、平行四辺形では4点の座標値が返される。

検出された輪郭のうち面積の大きいもののみ識別する。

areas = []
for cnt in contours:
    area = cv2.contourArea(cnt)
    if area > 10000:
        epsilon = 0.1*cv2.arcLength(cnt,True)
        approx = cv2.approxPolyDP(cnt,epsilon,True)
        areas.append(approx)

検出された輪郭を画像上に重ねるにcv2.drawContours()を用いる。

cv2.drawContours(src,areas,-1,(255,0,0),3)
plt.imshow(src)

以下のように名刺部分の輪郭が正しく抽出できていることがわかる。

"輪郭抽出画像"
輪郭抽出画像

2. 台形補正処理と効果

 画像から輪郭抽出された座標を用いて、台形補正処理を行う。補正後の座標は、前回と同様に輪郭点同士の長さを算出することで幅、高さ情報を得る。 ここで抽出された座標が左上、右上、左下、右下といった具合に、補正後の座標点と対応させるために並び替える必要がある。例えば左に傾いた名刺であれば以下のようにして自動的に並び替える。 ただし、右や奥など任意の傾きに関しては、もう少し方法に工夫が必要。

pt1ind=np.argmin(areas[0],axis=0)[0][0]
pt1=areas[0][pt1ind] #左上
pt2ind=np.argmin(areas[0],axis=0)[0][1]
pt2=areas[0][pt2ind] #右上
pt3ind=np.argmax(areas[0],axis=0)[0][1]
pt3=areas[0][pt3ind] #左下
pt4ind=np.argmax(areas[0],axis=0)[0][0]
pt4=areas[0][pt4ind] #右下
pts = np.float32(np.array([pt1,pt2,pt3,pt4]))
o_width = np.linalg.norm(pt2 - pt1)
o_width=int(np.floor(o_width))
o_height = np.linalg.norm(pt3 - pt1)
o_height=int(np.floor(o_height))
dst_cor=np.float32([[0,0],[o_width,0],[0, o_height],[o_width, o_height]])

以下は前回と同じで、輪郭座標と変換後座標を指定して、台形補正処理を行う変換行列を取得して元画像に適用する。

M = cv2.getPerspectiveTransform(pts,dst_cor)
dst = cv2.warpPerspective(src,M,(o_width,o_height))
plt.imshow(dst)

少し歪みがあるものの(元画像の名刺が少し反っている影響?)名刺の文字が正しく表示されていることがわかる。

"台形補正処理後のテスト名刺画像"
台形補正処理後のテスト名刺画像

文字が少し薄いので、2値化画像に対して台形補正処理すると、少し潰れているものの(2値化処理の閾値の加減で調整)文字がはっきりとわかる。

dst2 = cv2.warpPerspective(th1,M,(o_width,o_height))
plt.imshow(dst2,cmap='gray')

"台形補正処理後の2値化画像"
台形補正処理後の2値化画像

3. まとめ

 OpenCVの台形補正で、変換座標を自動的に抽出して台形補正処理を行う方法について紹介した。基本的には輪郭抽出がうまくいかないと座標抽出ができないので、今回の名刺画像のように背景と補正対象物のコントラストがはっきり区別できる場合は有効である。

OpenCVの使い方8 ~ 台形補正

 今回はOpenCVを使った台形補正処理の方法について紹介したい。

1. 台形補正

台形補正とは、撮影角度によって斜め・台形になった画像を正面から撮影したように補正する処理のことで、多くの画像処理ソフトなどに実装されている基本的な画像処理の1つになる。

OpenCVの処理に流れは、以前紹介した幾何変換と同様で、

atatat.hatenablog.com

変換前の座標点と変換後の座標点から変換行列(台形補正の場合はcv2.getPerspectiveTransform)を求めて、補正する画像に変換(cv2.warpPerspective)を適用する。

今回は画像やコードは以下を参考にして台形補正を実行した。

self-development.info

2. 変換座標の取得

 テスト画像を読み込んで表示させると以下のようになる。

サンプル画像読み込み

import cv2
import numpy as np
from matplotlib import pyplot as plt
from google.colab import files
uploaded_file = files.upload()
uploaded_file_name = next(iter(uploaded_file))
orig = cv2.imread(uploaded_file_name)
src = cv2.cvtColor(orig, cv2.COLOR_BGR2RGB)
plt.imshow(src)

"テスト画像"
テスト画像

テスト画像中の赤丸で示している4点を正面から見た長方形4点に変換する変換行列を求めて画像データに適用することで台形補正を行う。

なお使用している画像サイズは上記のリンクと異なるため、ペイントなど画像座標が表示されるソフトを用いて赤丸4点の座標を調べると左上p1(46,159), 右上p2(421,64), 左下p3(38,246), 右下p4(428,174)となった。 変換後の座標は、幅を左上p1、右上p2、高さを左上p1、左下p3の長さをnp.linalg.norm()で取得しint型にすることで、長方形4点の座標を得る。変換前後の4点の座標を配列ori_cor,dst_corとして格納する。 具体的には以下のようにコードを記述する。

p1 = np.array([46,159]) #左上
p2 = np.array([421,64]) #右上
p3 = np.array([38,246]) #左下
p4 = np.array([428,174]) #右下

o_width = np.linalg.norm(p2 - p1)
o_width=int(np.floor(o_width))
o_height = np.linalg.norm(p3 - p1)
o_height=int(np.floor(o_height))

ori_cor = np.float32([p1, p2, p3, p4])
dst_cor=np.float32([[0, 0],[o_width, 0],[0, o_height],[o_width, o_height]])

3. 台形補正

 変換前、後の4点の座標を格納した配列ori_cor,dst_corから台形補正に用いる変換行列Mを cv2.getPerspectiveTransform(ori_cor, dst_cor)により得たあと、cv2.warpPerspective(src, M,(o_width, o_height)) により画像データに適用する。

M = cv2.getPerspectiveTransform(ori_cor, dst_cor)
cor_src = cv2.warpPerspective(src, M,(o_width, o_height))

plt.imshow(cor_src)

台形補正後の画像は以下のようになり、斜めになっていた看板が正面から撮影したような画像に変換されている。

"台形補正後の画像"
台形補正後の画像

4. まとめ

 今回はOpenCVを用いた台形補正処理の方法について紹介した。基本的には変換前後、4点の画像上の座標を指定して変換行列を取得、あとは補正する画像データに適用するという流れで台形補正を実行することができる。