1. 程式人生 > >OpenCV影象處理--為影象新增Logo

OpenCV影象處理--為影象新增Logo

1,目的

將logo圖示疊加到一張圖片的右上角,要求有顏色的區域為不透明,例如將阿里影業的Logo疊加到戰狼2的海報上,原始圖和效果圖如下。

wolf.jpg

ali-movie.png

img_target.png

2,思路

不同的logo有不同的處理方法,有的是黑色需要透明,有的是白色需要透明,但是,整理的思路是一致的。

如下圖所示,從上向下,對要形成的效果進行分解,一共分為3層。

  • 第一層需要第二層的兩張圖片,做cv2.add運算即可
  • 第二層第一張圖片需要第三層前兩張圖片,做cv2.bitwise_and運算即可,後一張做mask
  • 第二層第二張圖片需要第三層後兩張圖片,做cv2.bitwise_and運算即可,後一張做mask

method of img deal.png

在分解過程中,需要思考和明確要呼叫的OpenCV函式。如果一步解決不了,就拆分成多步解決。

3,步驟分析

基於上述思路,制定詳細的影象處理步驟,並進行編碼除錯。處理步驟如下圖所示。

ali-logo deal process.png

3.1,讀取logo圖片,並對logo按照20%進行縮放

img_logo = cv2.imread("d:/1/ali-movie.png", cv2.IMREAD_COLOR)
img_logo = cv2.resize(img_logo, (0, 0), fx=0.2, fy=0.2, interpolation=cv2.INTER_NEAREST)

3.2,對logo進行灰度化處理,得到兩個mask

img_logo_gray = cv2.cvtColor(img_logo, cv2.COLOR
_BGR2GRAY) ret, img_logo_mask = cv2.threshold(img_logo_gray, 200, 255, cv2.THRESH_BINARY) # 二值化函式 img_logo_mask1 = cv2.bitwise_not(img_logo_mask)

3.3,提取目標圖片的ROI

img_target = cv2.imread("d:/1/wolf.jpg", cv2.IMREAD_COLOR)
rows, cols, channel = img_logo.shape
rows1, cols1, channel1 = img_target.shape
img_roi = img_target[:rows, cols1 - cols:cols1].copy()

3.4,ROI和Logo影象融合

img_res0 = cv2.bitwise_and(img_roi, img_roi, mask=img_logo_mask)
img_res1 = cv2.bitwise_and(img_logo, img_logo, mask=img_logo_mask1)
img_res2 = cv2.add(img_res0, img_res1)
# img_res2 = img_res0 + img_res1
img_target[:rows, cols1 - cols:cols1] = img_res2[:, :]
cv2.imwrite("img_target.png", img_target)

4,疑難點介紹

4.1,cv2.add與矩陣相加的區別

測試程式

import numpy as np
import cv2
x = np.uint8([250])
y = np.uint8([10])
print cv2.add(x,y)   #輸出# [[255]]
print x+y            #輸出# [4]  (250+10)%255

測試結論

  • cv2.add方法和numpy矩陣相加,都可以完成兩張圖片的相加運算
  • numpy矩陣相加是模運算
  • cv2.add是滲透運算,如果元素之和大於255,則按照255返回,可以直接相加兩張圖片試試效果,程式碼和效果圖如下所示
img_logo = cv2.imread("d:/1/ali-movie.png", cv2.IMREAD_COLOR)
img_target = cv2.imread("d:/1/wolf.jpg", cv2.IMREAD_COLOR)
print img_logo.shape, img_target.shape
img_new_add = cv2.add(img_target[:516, :798], img_logo[:516, :798])
cv2.imshow("img_new_add", img_new_add)
cv2.waitKey(0)
cv2.destroyAllWindows()

cv2.add.png

4.2,matplotlib的subplot簡單介紹

程式碼如下,效果圖如method of img deal.png所示。

  • 程式碼
# 顯示圖片,呼叫matplotlib展示
plt.figure()
plt.subplot(332), plt.imshow(img_convert(img_res2), cmap='gray'), plt.title("img_res2")
plt.subplot(323), plt.imshow(img_convert(img_res0), cmap='gray'), plt.title("img_res0")
plt.subplot(324), plt.imshow(img_convert(img_res1), cmap='gray'), plt.title("img_res1")
plt.subplot(3, 4, 9), plt.imshow(img_convert(img_roi), cmap='gray'), plt.title("img_roi")
plt.subplot(3, 4, 10), plt.imshow(img_convert(img_logo_mask), cmap='gray'), plt.title("img_logo_mask")
plt.subplot(3, 4, 11), plt.imshow(img_convert(img_logo), cmap='gray'), plt.title("img_logo")
plt.subplot(3, 4, 12), plt.imshow(img_convert(img_logo_mask1), cmap='gray'), plt.title("img_logo_mask1")
plt.show()
  • 效果圖

method of img deal.png

5,原始碼奉上

# coding:utf8

import numpy as np
import cv2
from matplotlib import pyplot as plt


# 影象處理,將logo圖示疊加到一張圖片的右上角,要求有顏色的區域為不透明
def img_deal():
    # 1,對logo進行縮放,按照20%進行
    img_logo = cv2.imread("d:/1/ali-movie.png", cv2.IMREAD_COLOR)
    img_logo = cv2.resize(img_logo, (0, 0), fx=0.2, fy=0.2, interpolation=cv2.INTER_NEAREST)
    # cv2.imshow("img_logo", img_logo)

    # 2,對logo做清洗,白色區域是255,其他區域置為黑色0
    img_logo_gray = cv2.cvtColor(img_logo, cv2.COLOR_BGR2GRAY)
    ret, img_logo_mask = cv2.threshold(img_logo_gray, 200, 255, cv2.THRESH_BINARY)  # 二值化函式
    img_logo_mask1 = cv2.bitwise_not(img_logo_mask)
    # cv2.imshow("img_logo_gray", img_logo_gray)
    # cv2.imshow("img_logo_mask", img_logo_mask)

    # 3,提取目標圖片的ROI
    img_target = cv2.imread("d:/1/wolf.jpg", cv2.IMREAD_COLOR)
    rows, cols, channel = img_logo.shape
    rows1, cols1, channel1 = img_target.shape
    img_roi = img_target[:rows, cols1 - cols:cols1].copy()
    # cv2.imshow("img_roi", img_roi)

    # 4,ROI和Logo影象融合
    img_res0 = cv2.bitwise_and(img_roi, img_roi, mask=img_logo_mask)
    img_res1 = cv2.bitwise_and(img_logo, img_logo, mask=img_logo_mask1)
    img_res2 = cv2.add(img_res0, img_res1)
    # img_res2 = img_res0 + img_res1
    img_target[:rows, cols1 - cols:cols1] = img_res2[:, :]
    cv2.imwrite("img_target.png", img_target)

    # 顯示圖片,呼叫opencv展示
    # cv2.imshow("img_res0", img_res0)
    # cv2.imshow("img_res1", img_res1)
    # cv2.imshow("img_res2", img_res2)
    # cv2.imshow("img_target", img_target)
    # cv2.waitKey(0)
    # cv2.destroyAllWindows()

    # 顯示圖片,呼叫matplotlib展示
    plt.figure()
    titles = ["img_logo", "img_logo_gray", "img_logo_mask", "img_logo_mask1", "img_roi", "img_res0", "img_res1",
              "img_res2"]
    imgs = [img_logo, img_logo_gray, img_logo_mask, img_logo_mask1, img_roi, img_res0, img_res1, img_res2]
    for x in xrange(len(imgs)):
        plt.subplot(241 + x), plt.imshow(img_convert(imgs[x]), cmap='gray'), plt.title(titles[x])  # , plt.axis('off')
    plt.show()

    # 顯示圖片,呼叫matplotlib展示
    plt.figure()
    plt.subplot(332), plt.imshow(img_convert(img_res2), cmap='gray'), plt.title("img_res2")
    plt.subplot(323), plt.imshow(img_convert(img_res0), cmap='gray'), plt.title("img_res0")
    plt.subplot(324), plt.imshow(img_convert(img_res1), cmap='gray'), plt.title("img_res1")
    plt.subplot(3, 4, 9), plt.imshow(img_convert(img_roi), cmap='gray'), plt.title("img_roi")
    plt.subplot(3, 4, 10), plt.imshow(img_convert(img_logo_mask), cmap='gray'), plt.title("img_logo_mask")
    plt.subplot(3, 4, 11), plt.imshow(img_convert(img_logo), cmap='gray'), plt.title("img_logo")
    plt.subplot(3, 4, 12), plt.imshow(img_convert(img_logo_mask1), cmap='gray'), plt.title("img_logo_mask1")
    plt.show()


# cv2與matplotlib的影象轉換,cv2是bgr格式,matplotlib是rgb格式
def img_convert(cv2_img):
    # 灰度圖片直接返回
    if len(cv2_img.shape) == 2:
        return cv2_img
    # 3通道的BGR圖片
    elif len(cv2_img.shape) == 3 and cv2_img.shape[2] == 3:
        b, g, r = cv2.split(cv2_img)
        return cv2.merge((r, g, b))
    # 4通道的BGR圖片
    elif len(cv2_img.shape) == 3 and cv2_img.shape[2] == 4:
        b, g, r, a = cv2.split(cv2_img)
        return cv2.merge((r, g, b, a))
    # 未知圖片格式
    else:
        return cv2_img


# 主函式
if __name__ == "__main__":
    img_deal()

6,參考頁面