第3回 課題解答

元画像の例

課題1 : X方向のスキュー

from PIL import Image
import math
 
# 画像を開く
img = Image.open('source.jpg')
 
# 角度を指定して画像をX方向にスキューさせる
angle = math.radians(-30)
 
# 画像のサイズを取得
width, height = img.size
 
# 新しい画像のサイズを計算
new_width = int(width + height * abs(math.tan(angle)))
 
# 新しい画像を作成
new_img = Image.new('RGB', (new_width, height), (255, 255, 255))
 
# 画像をスキューさせる
for y in range(height):
  for x in range(width):
    # angleが正の場合
    if angle > 0:
      new_x = int(x + y * math.tan(angle))
    # angleが負の場合
    else:
      new_x = int(x + y * math.tan(angle) + height * abs(math.tan(angle)))
    # 計算した座標が範囲内なら
    if 0 <= new_x < new_width:
      new_img.putpixel((new_x, y), img.getpixel((x, y)))
 
# 画像を保存
new_img.save('1_2.jpg')
できる画像 (X方向30°スキュー)

できる画像 (X方向-30°スキュー)

課題2 : Y方向のスキュー

from PIL import Image
import math
 
# 画像を開く
img = Image.open('source.jpg')
 
# 角度を指定して画像をY方向にスキューさせる
angle = math.radians(-30)
 
# 画像のサイズを取得
width, height = img.size
 
# 新しい画像のサイズを計算
new_height = int(height + width * abs(math.tan(angle)))
 
# 新しい画像を作成
new_img = Image.new('RGB', (width, new_height), (255, 255, 255))
 
# 画像をスキューさせる
for y in range(height):
  for x in range(width):
    # angleが正の場合
    if angle > 0:
      new_y = int(y + x * math.tan(angle))
    # angleが負の場合
    else:
      new_y = int(y + x * math.tan(angle) + width * abs(math.tan(angle)))
    # 計算した座標が範囲内なら
    if 0 <= new_y < new_height:
      new_img.putpixel((x, new_y), img.getpixel((x, y)))
 
# 画像を保存
new_img.save('2_2.jpg')
できる画像 (Y方向30°スキュー)

できる画像 (Y方向-30°スキュー)

課題3 : X方向のスキュー (OpenCV)

import cv2
import numpy as np
import math
 
# 画像を開く
img = cv2.imread('source.jpg')
 
# 角度を指定して画像をX方向にスキューさせる
angle = math.radians(-30)
 
# 画像のサイズを取得
height, width = img.shape[:2]
 
# 新しい画像のサイズを計算
new_width = int(width + height * abs(math.tan(angle)))
 
# 変換行列を作成する
# angleが正の場合
if angle > 0:
  M = np.float32([[1, math.tan(angle), 0], [0, 1, 0]])
# angleが負の場合
else:
  M = np.float32([[1, math.tan(angle), -height * math.tan(angle)], [0, 1, 0]])
 
# 画像をスキューさせる
img_skew = cv2.warpAffine(img, M, (new_width, height))
 
# 画像を保存する
cv2.imwrite('3_2.jpg', img_skew)
できる画像 (X方向30°スキュー)

できる画像 (X方向-30°スキュー)

課題4 : Y方向のスキュー (OpenCV)

import cv2
import numpy as np
import math
 
# 画像を開く
img = cv2.imread('source.jpg')
 
# 角度を指定して画像をY方向にスキューさせる
angle = math.radians(-30)
 
# 画像のサイズを取得
height, width = img.shape[:2]
 
# 新しい画像のサイズを計算
new_height = int(height + width * abs(math.tan(angle)))
 
# 変換行列を作成する
# angleが正の場合
if angle > 0:
  M = np.float32([[1, 0, 0], [math.tan(angle), 1, 0]])
# angleが負の場合
else:
  M = np.float32([[1, 0, 0], [math.tan(angle), 1, -width * math.tan(angle)]])
 
# 画像をスキューさせる
img_skew = cv2.warpAffine(img, M, (width, new_height))
 
# 画像を保存する
cv2.imwrite('4_2.jpg', img_skew)
できる画像 (Y方向30°スキュー)

できる画像 (Y方向-30°スキュー)