最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Python OpenCV實(shí)現(xiàn)圖像的覆蓋

 更新時(shí)間:2022年02月10日 09:21:19   作者:求則得之,舍則失之  
本文將基于Python、OpenCV和Numpy實(shí)現(xiàn)圖像的覆蓋,即小圖像覆蓋在大圖像上。文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下

前言

在本文中,我將展示如何將對(duì)象從一個(gè)圖像添加到另一個(gè)圖像。為此,我們需要:

1.背景圖像;

2.對(duì)象

3.對(duì)象的mask(mask為黑色,其他空間為白色)。

在我們的例子中,背景是一張大海的照片,對(duì)象是一杯咖啡。在這里,他們是:

1.導(dǎo)入相關(guān)庫

現(xiàn)在,使用jupiter notebook創(chuàng)建一個(gè)新文件。首先,我們需要導(dǎo)入必要的模塊:

import cv2 # OpenCV
import numpy as np
import matplotlib.pyplot as plt

2.使用OpenCV讀取和顯示圖像

讓我們?cè)赾v2.imread()函數(shù)的幫助下打開圖像并顯示它們。

注意!

由于某些原因,OpenCV以BGR格式讀取圖像(藍(lán)色和紅色被交換)。我們需要借助cv2.cvtColor()函數(shù)將BGR轉(zhuǎn)換為RGB格式。

# Original image, which is the background?
background = cv2.imread('background.jpg')
background = cv2.cvtColor(background, cv2.COLOR_BGR2RGB)

# Image of the object
img = cv2.imread('cup.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# Image the object's mask
mask = cv2.imread('cup_mask.png')
mask = cv2.cvtColor(mask, cv2.COLOR_BGR2RGB)

print("Background shape:", background.shape)
print("Image shape:", img.shape)
print("Mask shape:", img.shape)
# Background shape: (1280, 1920, 3)
# Image shape: (860, 1151, 3)
# Mask shape: (860, 1151, 3)

我們看到背景圖像的高度為1280,寬度為1920,目標(biāo)圖像的高度為860,寬度為1151。

讓我們看看這些圖片:

plt.figure(figsize=(16,16))
plt.title("Background", fontsize=18)
plt.imshow(background);

fig, ax = plt.subplots(1, 2, figsize=(16, 7))
ax[0].imshow(img)
ax[0].set_title('Object', fontsize=18)
ax[1].imshow(mask)
ax[1].set_title('Mask', fontsize=18);

3.從物體的圖像中去除背景

現(xiàn)在我們將定義一個(gè)函數(shù),它將對(duì)象的mask轉(zhuǎn)換為布爾數(shù)組。

在原始mask上,對(duì)象區(qū)域填充黑色,背景區(qū)域填充白色。

布爾數(shù)組具有與原始mask相同的高度和寬度,但只有一個(gè)通道。如果一個(gè)像素屬于對(duì)象區(qū)域,它的值為True,否則為False。

布爾mask將幫助我們刪除所有的背景像素。

def remove_obj_background(img_path, mask_path):
? ? '''
? ? Function returns:
? ? - image of the object with removed background in CV2 RGB format (numpy array with dimensions (width, height, 3))
? ? - boolean mask of the object (numpy array with dimensions (width, height))
? ? '''
? ? img = cv2.imread(img_path)
? ? img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
? ??
? ? mask = cv2.imread(mask_path)
? ? mask = cv2.cvtColor(mask, cv2.COLOR_BGR2RGB)?
? ??
? ? h, w = mask.shape[0], mask.shape[1]
? ??
? ? # Boolean mask is a numpy array with two dimensions: width and height.
? ? # On the original mask, object area is filled with black color, background area is filled with white color.
? ? # On the boolean mask, object area is filled with True, background area is filled with False.
? ? mask_boolean = mask[:,:,0] == 0
? ? img_with_removed_background = img * np.stack([mask_boolean, mask_boolean, mask_boolean], axis=2)
? ??
? ? return img_with_removed_background, mask_boolean

img_with_removed_background, mask_boolean = remove_obj_background('cup.png', 'cup_mask.png')
print("Shape of the image of the object:", img_with_removed_background.shape)
print("Shape of the boolean mask:", mask_boolean.shape)
print("\n")
# Image with removed background shape: (860, 1151, 3)
# Boolean mask shape: (860, 1151)

fig, ax = plt.subplots(1, 2, figsize=(16, 7))
ax[0].imshow(img_with_removed_background)
ax[0].set_title('Object with removed background', fontsize=18)
ax[1].imshow(mask_boolean)
ax[1].set_title('Boolean mask', fontsize=18);

4.添加對(duì)象到背景圖像

在我們定義向背景圖像添加對(duì)象的函數(shù)之前,我需要解釋和可視化幾個(gè)圖像重疊的情況。

比如說,背景圖像的高度是h_background,寬度是w_background,而目標(biāo)圖像的高度是h,寬度是w。

h應(yīng)該小于h_background, w應(yīng)該小于w_background。

case1) 如果我們將物體放置在背景的中間,那么一切都很簡(jiǎn)單:大小為h x w的背景區(qū)域部分應(yīng)該被物體替換掉。

case2) 如果我們將物體放置在背景的左上角,那么物體的一部分可能在背景區(qū)域之外。在這種情況下,背景區(qū)域的大小(h - y) x (w - x)的部分應(yīng)該被替換為對(duì)象。

這里-x和-y是對(duì)象圖像左上角的坐標(biāo)。符號(hào)' - '在這里是因?yàn)楸尘皥D像的左上角坐標(biāo)x=0和y=0。從背景圖像的左上角到對(duì)象左上角的所有區(qū)域的x坐標(biāo)都是負(fù)的,高于背景圖像的左上角的所有區(qū)域的y坐標(biāo)都是負(fù)的。

case3) 如果我們將物體放置在背景的左下角,那么物體的一部分可能在背景區(qū)域之外。在這種情況下,背景區(qū)域大小為(h_background - y) x (w - x)的部分應(yīng)該被替換為對(duì)象。

一般,面積可以計(jì)算為(h - max (0, y + h - h_background)) x (w - x),因?yàn)槿绻繕?biāo)圖像的最低邊界在背景圖像的最低邊界之上,那么h x (w - x)區(qū)域應(yīng)該被替換為目標(biāo)。

case4) 如果我們將物體放在背景的右上角,那么物體的一部分可能會(huì)在背景區(qū)域之外。在這種情況下,大小為 (h - y) x (w_background - x) 的背景區(qū)域部分應(yīng)替換為對(duì)象。

一般來說,面積可以計(jì)算為 (h - y) x (w - max(0, x + w - w_background)),因?yàn)槿绻矬w圖像的右邊界在背景圖像右邊界的左側(cè),則 (h - y) x w 區(qū)域應(yīng)替換為對(duì)象。

case5) 如果我們將物體放在背景的右下角,那么物體的一部分可能會(huì)在背景區(qū)域之外。在這種情況下,大小為 (h_background - y) x (w_background - x) 的背景區(qū)域部分應(yīng)替換為對(duì)象。

一般來說,面積可以計(jì)算為 (h - max(0, y + h - h_background)) x (w - max(0, x + w - w_background)),因?yàn)槿绻矬w圖像的右側(cè)部分在背景圖像的右部分的左邊,如果對(duì)象圖像的最低部分高于背景圖像的最低部分,則應(yīng)將h x w區(qū)域替換為對(duì)象。

現(xiàn)在,考慮到上述所有情況,讓我們定義函數(shù):

def add_obj(background, img, mask, x, y):
    '''
    Arguments:
    background - background image in CV2 RGB format
    img - image of object in CV2 RGB format
    mask - mask of object in CV2 RGB format
    x, y - coordinates of the center of the object image
    0 < x < width of background
    0 < y < height of background
    
    Function returns background with added object in CV2 RGB format
    
    CV2 RGB format is a numpy array with dimensions width x height x 3
    '''
    
    bg = background.copy()
    
    h_bg, w_bg = bg.shape[0], bg.shape[1]
    
    h, w = img.shape[0], img.shape[1]
    
    # Calculating coordinates of the top left corner of the object image
    x = x - int(w/2)
    y = y - int(h/2)    
    
    mask_boolean = mask[:,:,0] == 0
    mask_rgb_boolean = np.stack([mask_boolean, mask_boolean, mask_boolean], axis=2)
    
    if x >= 0 and y >= 0:
    
        h_part = h - max(0, y+h-h_bg) # h_part - part of the image which overlaps background along y-axis
        w_part = w - max(0, x+w-w_bg) # w_part - part of the image which overlaps background along x-axis

        bg[y:y+h_part, x:x+w_part, :] = bg[y:y+h_part, x:x+w_part, :] * ~mask_rgb_boolean[0:h_part, 0:w_part, :] + (img * mask_rgb_boolean)[0:h_part, 0:w_part, :]
        
    elif x < 0 and y < 0:
        
        h_part = h + y
        w_part = w + x
        
        bg[0:0+h_part, 0:0+w_part, :] = bg[0:0+h_part, 0:0+w_part, :] * ~mask_rgb_boolean[h-h_part:h, w-w_part:w, :] + (img * mask_rgb_boolean)[h-h_part:h, w-w_part:w, :]
        
    elif x < 0 and y >= 0:
        
        h_part = h - max(0, y+h-h_bg)
        w_part = w + x
        
        bg[y:y+h_part, 0:0+w_part, :] = bg[y:y+h_part, 0:0+w_part, :] * ~mask_rgb_boolean[0:h_part, w-w_part:w, :] + (img * mask_rgb_boolean)[0:h_part, w-w_part:w, :]
        
    elif x >= 0 and y < 0:
        
        h_part = h + y
        w_part = w - max(0, x+w-w_bg)
        
        bg[0:0+h_part, x:x+w_part, :] = bg[0:0+h_part, x:x+w_part, :] * ~mask_rgb_boolean[h-h_part:h, 0:w_part, :] + (img * mask_rgb_boolean)[h-h_part:h, 0:w_part, :]
    
    return bg

除了將背景、對(duì)象和mask圖像傳遞給函數(shù)外,我們還將傳遞坐標(biāo)x和y,它們定義了對(duì)象的中心位置。

坐標(biāo)(0,0)是背景的左上角。

w_bg和h_bg是背景的寬度和高度。

x和y應(yīng)滿足以下條件:0 < x < w_bg和0 < y < h_bg。

5.結(jié)果展示

讓我們看看這個(gè)函數(shù)是如何工作的。

例1). 讓我們把杯子放在背景的中央。背景的寬度是1920,高度是1280,所以對(duì)象的中心坐標(biāo)是x=1920/2=960和y=1280/2=640。

composition_1 = add_obj(background, img, mask, 960, 640)
plt.figure(figsize=(15,15))
plt.imshow(composition_1);

例2). 讓我們把杯子放在背景的左下角。這一次,對(duì)象的中心坐標(biāo)是x=200和y=1100。

composition_2 = add_obj(composition_1, img, mask, 200, 1100)
plt.figure(figsize=(15,15))
plt.imshow(composition_2);

例 3). 讓我們把杯子放在背景的右下角。這次對(duì)象中心的坐標(biāo)是 x=1800 和 y=1100。

composition_3 = add_obj(composition_2, img, mask, 1800, 1100)
plt.figure(figsize=(15,15))
plt.imshow(composition_3);

例 4). 讓我們把杯子放在背景的左上角。這次對(duì)象中心的坐標(biāo)是 x=200 和 y=200。

composition_4 = add_obj(composition_3, img, mask, 200, 200)
plt.figure(figsize=(15,15))
plt.imshow(composition_4);

例5). 讓我們把杯子放在背景的右上角。這一次,對(duì)象的中心坐標(biāo)是x=1800和y=200。

composition_5 = add_obj(composition_4, img, mask, 1800, 200)
plt.figure(figsize=(15,15))
plt.imshow(composition_5);

以上就是基于Python OpenCV實(shí)現(xiàn)圖像的覆蓋的詳細(xì)內(nèi)容,更多關(guān)于Python OpenCV圖像覆蓋的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Python批量創(chuàng)建迅雷任務(wù)及創(chuàng)建多個(gè)文件

    Python批量創(chuàng)建迅雷任務(wù)及創(chuàng)建多個(gè)文件

    其實(shí)不是真的創(chuàng)建了批量任務(wù),而是用python創(chuàng)建一個(gè)文本文件,每行一個(gè)要下載的鏈接,然后打開迅雷,復(fù)制文本文件的內(nèi)容,迅雷監(jiān)測(cè)到剪切板變化,彈出下載全部鏈接的對(duì)話框
    2016-02-02
  • Python小工具之消耗系統(tǒng)指定大小內(nèi)存的方法

    Python小工具之消耗系統(tǒng)指定大小內(nèi)存的方法

    今天小編就為大家分享一篇Python小工具之消耗系統(tǒng)指定大小內(nèi)存的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-12-12
  • pycharm編寫spark程序,導(dǎo)入pyspark包的3中實(shí)現(xiàn)方法

    pycharm編寫spark程序,導(dǎo)入pyspark包的3中實(shí)現(xiàn)方法

    這篇文章主要介紹了pycharm編寫spark程序,導(dǎo)入pyspark包的3中實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-08-08
  • Python實(shí)現(xiàn)批量文件分類保存的示例代碼

    Python實(shí)現(xiàn)批量文件分類保存的示例代碼

    當(dāng)我們電腦里面的文本或者或者文件夾太多了,有時(shí)候想找到自己想要的文件,只能通過去搜索文件名,這樣還是很麻煩的。本文將通過Python語言實(shí)現(xiàn)文件批量分類保存,需要的可以參考一下
    2022-04-04
  • python將多張圖片合并成一張圖片的過程

    python將多張圖片合并成一張圖片的過程

    這篇文章主要介紹了python將多張圖片合并成一張圖片的全過程,文中通過代碼示例和圖文給大家講解的非常詳細(xì),對(duì)大家學(xué)習(xí)使用python將多張圖片合并成一張圖片有一定的幫助,需要的朋友可以參考下
    2024-03-03
  • python如何將txt坐標(biāo)批量打印到原圖上

    python如何將txt坐標(biāo)批量打印到原圖上

    這篇文章主要介紹了python如何將txt坐標(biāo)批量打印到原圖上的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • python如何實(shí)現(xiàn)單向鏈表及單向鏈表的反轉(zhuǎn)

    python如何實(shí)現(xiàn)單向鏈表及單向鏈表的反轉(zhuǎn)

    這篇文章主要介紹了python如何實(shí)現(xiàn)單向鏈表及單向鏈表的反轉(zhuǎn),幫助大家更好的理解和學(xué)習(xí)使用python,感興趣的朋友可以了解下
    2021-03-03
  • Python request操作步驟及代碼實(shí)例

    Python request操作步驟及代碼實(shí)例

    這篇文章主要介紹了Python request操作步驟及代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • python基礎(chǔ)之集合

    python基礎(chǔ)之集合

    這篇文章主要介紹了python集合,實(shí)例分析了Python中返回一個(gè)返回值與多個(gè)返回值的方法,需要的朋友可以參考下
    2021-10-10
  • Python分類測(cè)試代碼實(shí)例匯總

    Python分類測(cè)試代碼實(shí)例匯總

    這篇文章主要介紹了Python分類測(cè)試代碼實(shí)例匯總,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07

最新評(píng)論

合川市| 定兴县| 太白县| 卫辉市| 陆丰市| 封开县| 桐乡市| 高青县| 天镇县| 宿州市| 龙江县| 社会| 商洛市| 平度市| 临安市| 太仓市| 张北县| 富宁县| 武邑县| 舟山市| 离岛区| 高阳县| 江源县| 县级市| 西峡县| 萨迦县| 安顺市| 岑巩县| 济南市| 石楼县| 兴化市| 新源县| 嘉黎县| 绥中县| 清远市| 慈利县| 翁牛特旗| 宁武县| 赤城县| 宁津县| 化州市|