那曲檬骨新材料有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

使用Python+OpenCV處理圖片

安費諾傳感器學堂 ? 來源:安費諾傳感器學堂 ? 2024-12-23 15:54 ? 次閱讀

如果給你一張圖片作為背景,另外一張圖片中的物體作為前景圖,要把前景圖中的物體疊加布置到背景圖的中間位置,并且前景圖中的物體需要在背景圖中有旋轉和投影,怎么處理?

如果是一兩張圖,PS應該是首選,但是如果是批量的呢?這就是小編要準備處理的一個小問題。挑戰一下,用Python+OpenCV來實現這個小目標。

提出問題和解決思路

作為前景的圖片的背景是白色不透明的,不過這就有條件實現摳圖了

前景圖的尺寸甚至比背景圖大,要縮小并且要算出位置

如果圖片沒有透明層來控制,則需要轉換并添加透明層

疊加的前景圖需要可以控制旋轉角度,但旋轉同時也影響前景圖的尺寸

摳圖進行疊加效果不好怎么辦?要進行羽化模糊化處理

為了讓圖片的疊加更加自然,還要考慮讓前景物體在背景上投個影

代碼驗證

1. 摳圖,取出前景物體的兩種處理方式比較

為了看到中間過程,代碼中添加了加輪廓線和掩碼圖兩個中間圖的輸出。

1.1 通過cv2.bitwise_and()函數處理輪廓掩碼

下面首先使用cv2.bitwise_and()函數處理。掩碼圖是有透明度控制層的,每個像素,在輪廓線外的的像素值是(B, G, R, A)=(0,0,0,0),輪廓線內的像素值是(B, G, R, A)=(255,255,255,255)。這種情況下,前景圖中任何在輪廓線外的像素和掩碼圖對應位置的掩碼像素進行按位“與”操作時,都會變成透明‘人’,而輪廓線內部的原圖像素則會保留原值。

這里OpenCV中的一個函數是個關鍵。注意閾值thresh。


contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

import cv2
import numpy as np
import tkinter as tk


def get_display_size():
    root = tk.Tk()
    width = root.winfo_screenwidth()
    height = root.winfo_screenheight()
    root.quit()
    return width, height


def extract_contour_from_jpg(image_path, output_path):
    # 讀取JPEG圖像
    image = cv2.imread(image_path)
    # 如果是 JPG 圖像,轉換為 BGRA 格式以支持透明度
    if image.shape[2] == 3:  # Assuming BGR without alpha
        image = cv2.cvtColor(image, cv2.COLOR_BGR2BGRA)
    # 轉換為灰度圖像
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)


    # 應用閾值操作以找到物體
_,thresh=cv2.threshold(gray,240,255,cv2.THRESH_BINARY_INV)
    
    # 找到輪廓
    contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)


#創建一個全透明的背景
    result = np.zeros_like(image)


    # 在原圖區域上填充在掩碼中不透明的區域
    for contour in contours:
        cv2.drawContours(result, [contour], -1, (255, 255, 255, 255), thickness=cv2.FILLED)


    # 在原圖上畫出輪廓線
    # 獲取圖像的尺寸
    original_height, original_width = image.shape[:2]
    
#為輸出中間圖計算縮放比例
    display_size = get_display_size()
    scale_width = display_size[0] / original_width
    scale_height = display_size[1] / original_height
    scale = min(scale_width, scale_height)
    
    # 計算新的尺寸
    new_width = int(original_width * scale)
    new_height = int(original_height * scale)
    
    # 為輸出中間圖而調整圖像大小
    image_contours = image.copy()
    cv2.drawContours(image_contours, contours, -1, (0, 255, 0, 255), thickness=2) # 綠色的輪廓線
    resized_image = cv2.resize(image_contours, (new_width, new_height), interpolation=cv2.INTER_AREA)


    cv2.imshow('contours', resized_image)
    cv2.waitKey(0)
    
    # 僅保留原圖在不透明區域(內部)的像素
    resized_resultimage = cv2.resize(result, (new_width, new_height), interpolation=cv2.INTER_AREA)
    cv2.imshow('resized_resultimage', resized_resultimage)
    cv2.waitKey(0)
    
    result = cv2.bitwise_and(image, result)
    
    # 將結果圖像保存為支持透明度的文件格式(如PNG)
    cv2.imwrite(output_path, result)
    


# 使用示例
if __name__=='__main__':
    input_file = "Your_ForGround_Image_Path.png"


    output_file = "You_Output_transparent_Img_Path.png"


    extract_contour_from_jpg(input_file, output_file)

通過上面的代碼,我們可以得到前景圖中的物體,并且使得物體周邊的像素成為透明。下面的示意圖是在PPT中操作的,僅僅是為了顯示這個產品圖已經成功取出,在圖的背后添加了藍色。

我們看看細節。是不是無法忍受這些毛刺?

所以,通過“cv2.bitwise_and()”處理后得到的物體還是有點問題,我們需要對物體的周邊進行平滑處理。于是有了下面優化后的代碼,通過“cv2.GaussianBlur()”這個函數對得到的填充后的輪廓灰度圖的邊沿進行羽化處理,就可以對于輪廓的周邊進行平滑處理。

1.2 通過cv2.GaussianBlur()函數處理輪廓后的改善

我們直接上代碼。

import cv2
import numpy as np
import tkinter as tk


def get_display_size():
    root = tk.Tk()
    width = root.winfo_screenwidth()
    height = root.winfo_screenheight()
    root.quit()
    return width, height


def feather_object_contour(image_path, feather_size=10):
    # 讀取圖像
    image = cv2.imread(image_path, cv2.IMREAD_UNCHANGED)
    # 如果是 JPG 圖像,轉換為 BGRA 格式以支持透明度 / Convert JPG image to BGRA format to support transparency
    if image.shape[2] == 3:  # Assuming BGR without alpha
        image = cv2.cvtColor(image, cv2.COLOR_BGR2BGRA)
    # 獲取圖像的尺寸 / Get the dimensions of the image
    original_height, original_width = image.shape[:2]
    
    # 計算縮放比例 / Calculate scale ratio
    display_size = get_display_size()
    scale_width = display_size[0] / original_width
    scale_height = display_size[1] / original_height
    scale = min(scale_width, scale_height)
    
    # 計算新的尺寸 / Calculate new dimensions
    new_width = int(original_width * scale)
    new_height = int(original_height * scale)
    
    # 轉換為灰度圖像 / Convert to grayscale
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    
    # 二值化以識別物體 / Binarize to identify objects
    # 應用閾值,選擇較高的閾值來分離掉白色背景 / Apply threshold to separate white background
    _, thresh = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY_INV)


    # 查找物體的輪廓 / Find contours of the object
    contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)


    # 創建一個新圖像用于繪制輪廓 / Create a new image for drawing contours
    contour_mask = np.zeros_like(gray)


    # 在輪廓區域上填充 / Fill in the contour area
    for contour in contours:
        cv2.drawContours(contour_mask, [contour], -1, (255, 255, 255, 255), thickness=cv2.FILLED)
    
    # 對輪廓進行高斯模糊處理 / Apply Gaussian blur to the contour
    smoothed_mask = cv2.GaussianBlur(contour_mask, (feather_size, feather_size), 0)
    resized_image = cv2.resize(smoothed_mask, (new_width, new_height), interpolation=cv2.INTER_AREA)


    cv2.imshow('feathered_mask', resized_image)
    cv2.waitKey(0)
    
    # 確保圖像具有透明通道 / Ensure the image has an alpha channel
    if image.shape[2] == 3:
        image = cv2.cvtColor(image, cv2.COLOR_BGR2BGRA)
    
    # 應用羽化到透明通道 / Apply feathering to the alpha channel
    # 基于羽化輪廓掩模設置透明度 / Set alpha based on feathered contour mask
    smoothed_alpha = (smoothed_mask.astype(np.float32) / 255.0)
    alpha_channel = (255 * smoothed_alpha).astype(np.uint8)
    image[..., 3] = alpha_channel
    
    return image


# 使用示例
feathered_image=feather_object_contour('Your_ForGround_Image_Path.png',feather_size=5)
cv2.imshow('Blurred Img', feathered_image)
cv2.waitKey(0)
cv2.imwrite('You_Output_transparent_Img_Path.png', feathered_image)

下面是效果圖,可以和上面的圖進行比較。



2. 圖片疊加:前景圖和背景圖的疊加處理

既然有了上面PPT的效果,為什么還要用程序實現?

不如多問一句:如果類似的圖處理有很多呢?

把這個取出的前景圖按照比例進行縮放,移動,旋轉,得到新的前景圖,再通過前景圖中的像素的透明度來控制兩個圖的疊加效果。但是要增加投影的話,實際上需要第三個圖,也即投影圖,并且投影的圖中也需要一個柔和的過渡。

代碼中設置了前景圖和背景圖的比例關系,避免了合成之后前景圖尺寸的不一致。

合成圖片的代碼如下,效果圖后隨。

import cv2
import numpy as np


"""
要在圖像合成中使用羽化(或模糊)處理前景圖的透明邊緣附近,以便在背景圖上生成一個朝指定方向的陰影效果,可以通過以下步驟實現。
這個過程通常涉及到對前景圖的透明度(alpha 通道)進行處理,然后將其偏移并疊加到背景圖上。
"""
def create_shadow_effect(image, feather_size=10, shadow_offset=(10,10), shadow_color=(0, 0, 0, 128)):
    # 創建透明度通道的副本
    alpha = image[:, :, 3]


    # 使用高斯模糊處理 alpha 通道,以實現邊緣羽化
    feathered_alpha = cv2.GaussianBlur(alpha, (0, 0), sigmaX=feather_size, sigmaY=feather_size)
    
#創建一個純色圖層用于陰影效果
    shadow_layer = np.zeros_like(image)
    shadow_layer[:, :, :3] = shadow_color[:3]
    shadow_layer[:, :, 3] = feathered_alpha * (shadow_color[3] / 255.0)


    # 創建空白圖像作為陰影圖層
    shadow = np.zeros_like(image)
    x_offset, y_offset = shadow_offset


    # 調整大小以適應原圖像的邊界
    y_bound = min(shadow_layer.shape[0], shadow.shape[0] - y_offset)
    x_bound = min(shadow_layer.shape[1], shadow.shape[1] - x_offset)


    # 復制陰影到陰影圖層中
    shadow[y_offset:y_offset + y_bound, x_offset:x_offset + x_bound] = shadow_layer[:y_bound, :x_bound]


    return shadow


# 融合三個圖
def blend_images(background, foreground, shadow):
    for y in range(shadow.shape[0]):
        for x in range(shadow.shape[1]):
            # Blend shadow into the background
            alpha_shadow = shadow[y, x, 3] / 255.0
            background[y, x, :3] = (shadow[y, x, :3] * alpha_shadow +
                                    background[y, x, :3] * (1 - alpha_shadow))


    for y in range(foreground.shape[0]):
        for x in range(foreground.shape[1]):
            # Blend foreground into the background
            alpha_fg = foreground[y, x, 3] / 255.0
            background[y, x, :3] = (foreground[y, x, :3] * alpha_fg +
                                    background[y, x, :3] * (1 - alpha_fg))
# 旋轉,縮放以及融合            
def rotate_and_overlay(background_path, overlay_path, output_path, angle=30, feather_size=10):
    # 檢查前景圖有無透明層通道:創建一個帶有Alpha通道的
    bg_image = cv2.imread(background_path, cv2.IMREAD_UNCHANGED)
    if bg_image.shape[2] == 3:
        bg_image = cv2.cvtColor(bg_image, cv2.COLOR_BGR2BGRA)
    # 檢查背景圖有無透明層通道:創建一個帶有Alpha通道的
    fg_image = cv2.imread(overlay_path, cv2.IMREAD_UNCHANGED)
    if fg_image.shape[2] == 3:
        fg_image = cv2.cvtColor(fg_image, cv2.COLOR_BGR2BGRA)
        
    # 前景圖尺寸需要縮放
    original_height, original_width = fg_image.shape[:2]
    scale = 650.0/870.0
    
    # 計算新的尺寸
    fg_new_width = int(original_width * scale)
    fg_new_height = int(original_height * scale)
    
    # 新尺寸的前景圖
    fg_image = cv2.resize(fg_image, (fg_new_width, fg_new_height), interpolation=cv2.INTER_AREA)
    
    # 獲取前景圖像的中心
    fg_center = (fg_image.shape[1] // 2, fg_image.shape[0] // 2)


    # 創建旋轉矩陣(順時針旋轉30度)
    rot_matrix = cv2.getRotationMatrix2D(fg_center, angle, 1.0)


    # 計算旋轉后的圖像維度
    cos = np.abs(rot_matrix[0, 0])
    sin = np.abs(rot_matrix[0, 1])
    new_width = int((fg_image.shape[0] * sin) + (fg_image.shape[1] * cos))
    new_height = int((fg_image.shape[0] * cos) + (fg_image.shape[1] * sin))


    # 調整旋轉矩陣的移動量
    rot_matrix[0, 2] += (new_width / 2) - fg_center[0]
    rot_matrix[1, 2] += (new_height / 2) - fg_center[1]


    # 旋轉前景圖像
    rotated_fg = cv2.warpAffine(fg_image, rot_matrix, (new_width, new_height), 
                                borderMode=cv2.BORDER_CONSTANT, borderValue=(0, 0, 0, 0))


    # 創建陰影效果圖像
    shadow = create_shadow_effect(rotated_fg, feather_size=feather_size)
    
    # 將陰影和前景圖疊加到背景圖上
    x_offset = (bg_image.shape[1] - shadow.shape[1]) // 2
    y_offset = (bg_image.shape[0] - shadow.shape[0]) // 2
    
    blend_images(bg_image[y_offset:y_offset + shadow.shape[0], x_offset:x_offset + shadow.shape[1]], rotated_fg, shadow)


    # 保存結果圖像
    cv2.imwrite(output_path, bg_image)


# 調用示例
backGround_ImgPath='Your_backGround_ImgPath.png'
forGround_ImgPath = 'Your_forGround_ImgPath.png'
output_ImgPath = 'Your_output_ImgPath.png'
rotate_and_overlay(backGround_ImgPath, forGround_ImgPath, output_ImgPath, feather_size=5)

測試代碼的圖片疊加效果如下。

局部看起來還可以。甚至可以看到這個傳感器芯片的角度和前一個有一個轉角。是的,這里把前景圖整體轉動了一個指定的角度。

投影的效果看起來也比較自然。

上面就是小編要批量處理圖片的工具了,圖片量大的話,把代碼調整修改之后,就可以對文件夾中的所有圖片進行處理了,效率超過PhotoShop是沒有問題的。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 函數
    +關注

    關注

    3

    文章

    4346

    瀏覽量

    62965
  • OpenCV
    +關注

    關注

    31

    文章

    635

    瀏覽量

    41552
  • python
    +關注

    關注

    56

    文章

    4807

    瀏覽量

    85035

原文標題:用Python處理圖片:摳物體輪廓圖、透明化、圖片疊加以及圖中前景物體陰影的生成

文章出處:【微信號:安費諾傳感器學堂,微信公眾號:安費諾傳感器學堂】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    【Raspberry Pi 3試用體驗】+Opencv+python的人臉識別

    ;)看一下效果:光線不好還是能認出來,說明opencv自帶的分類器算開源里面不錯的了~參考:Tigerboard開發板試用體驗 python+opencv的人臉識別 NanoPi2試用體驗 簡單人臉識別-結項
    發表于 05-13 21:38

    基于機器學習庫opencv和平臺Jupyter Notebook的車牌識別案例

    python+opencv實現車牌識別
    發表于 02-28 11:08

    【Toybrick RK3399Pro AI開發板試用體驗】ACT Ⅵ:Linux下靜態人臉識別 python+opencv

    程序,只要點擊run即可,也不會報錯。看了網上很多教程,python+opencv,在有深度訓練源的情況下,7行代碼就能實現,那我們現在就來試一試。首先,我們要找一個訓練過的人臉的源,看了下大神的代碼,我
    發表于 08-10 10:50

    LabVIEW+Python+openCV

    的,動態鏈接庫也需要配置,還需要知道各個參數含義和類型,這里提供另外一種方法,那就是PythonopenCV工具包,絕對開源和免費,LabVIEW可以利用Python節點調用Python
    發表于 12-07 20:59

    OpenCV-Python-Toturial-中文版

    python編寫opencv的入門資料,介紹了python的各個函數的應用
    發表于 03-23 14:55 ?0次下載

    Python下使用OpenCV的技巧教程與典型應用案例

    Python下使用OpenCV教程,本篇將介紹和深度學習數據處理階段最相關的基礎使用,并完成4個有趣實用的小例子: - 延時攝影小程序 - 視頻中截屏采樣的小程序 - 圖片數據增加(
    發表于 11-15 18:43 ?1.2w次閱讀

    python圖像處理opencv步驟是怎么樣的

    越來越覺得python是一強大的工具,處理樣本確實不錯。最近因項目需要涉及到圖片處理,所以開始用python調用
    發表于 12-04 15:29 ?4430次閱讀

    OpenCV中的Python實現

    類構成,同時提供了Python、Ruby、MATLAB等語言的接口,實現了圖像處理和計算機視覺方面的很多通用算法。 OpenCV用C++語言編寫,它的主要接口也是C++語言,但是依然保留了大量的C語言
    的頭像 發表于 08-25 15:55 ?2105次閱讀

    使用opencvpython進行智能火災檢測

    電子發燒友網站提供《使用opencvpython進行智能火災檢測.zip》資料免費下載
    發表于 11-02 15:08 ?0次下載
    使用<b class='flag-5'>opencv</b>和<b class='flag-5'>python</b>進行智能火災檢測

    opencv讀入圖片注意事項詳解1

    深度學習數據預處理中常用opencv讀入圖片,一般在`__getitem__`函數中調用。本文主要介紹opencv讀取圖片的一些細節以及注意
    的頭像 發表于 02-07 16:06 ?663次閱讀

    opencv讀入圖片注意事項詳解 2

    深度學習數據預處理中常用opencv讀入圖片,一般在`__getitem__`函數中調用。本文主要介紹opencv讀取圖片的一些細節以及注意
    的頭像 發表于 02-07 16:06 ?702次閱讀

    如何使用Python+opencv進行圖像處理

    圖像是 Web 應用中除文字外最普遍的媒體格式。流行的 Web 靜態圖片有 JPEG、PNG、ICO、BMP 等。動態圖片主要是 GIF 格式。 為了節省圖片傳輸流量,大型互聯網公司還會定制特殊格式的
    的頭像 發表于 02-08 10:57 ?965次閱讀
    如何使用<b class='flag-5'>Python+opencv</b>進行圖像<b class='flag-5'>處理</b>

    OpenCV 如何加載圖片

    實現一遍。 OpenCV 的內容挺多的,而且不使用的話,容易忘記,所以通過制造工具的方式來給自己加深印象,平常要處理圖片的時候,就可以用自己的工具直接處理,不需要每次都去重復的寫代碼。
    的頭像 發表于 10-09 15:01 ?766次閱讀

    opencv-pythonopencv一樣嗎

    不一樣。OpenCV(Open Source Computer Vision Library)是一個開源的計算機視覺和機器學習軟件庫,它提供了大量的圖像和視頻處理功能。OpenCV-Python
    的頭像 發表于 07-16 10:38 ?1403次閱讀

    一個月速成python+OpenCV圖像處理

    OpenCV是一個廣受歡迎且極為流行的計算機視覺庫,它因其強大的功能、靈活性和開源特性而在開發者和研究者中備受青睞。學習OpenCV主要就是學習里面的計算機視覺算法。要學習這些算法的原理,知道它們
    的頭像 發表于 11-29 18:27 ?197次閱讀
    一個月速成<b class='flag-5'>python+OpenCV</b>圖像<b class='flag-5'>處理</b>
    博彩排名| 百家乐官网斗地主炸金花| 做生意风水门面要求| 威尼斯人娱乐城| 好运来百家乐官网现金网| 赌百家乐赢的奥妙| 青鹏棋牌游戏大厅v3.0| 蓝盾百家乐官网代理| 威尼斯人娱乐城客服| 百家乐官网高手技巧| 百家乐预约| 金宝博百家乐官网现金| 百家乐胜率被控制| 真人斗地主| 百家乐存在千术吗| 轮盘赌| 百家乐有多少种游戏| E世博线上娱乐城| 环球百家乐现金网| 渑池县| 网上百家乐返水| 顶尖百家乐官网对单| 百家乐椅子| 百家乐官网高手和勒威| 百家乐博赌城| 赌博百家乐官网经验网| 微信百家乐群规则大全| 百家乐官网赌场赌场网站| 全讯网博客| 广州百家乐官网娱乐场开户注册| 大发888网页登陆| 巴厘岛百家乐官网的玩法技巧和规则 | 真人百家乐免费开户送钱| 镶黄旗| 蓝盾百家乐的玩法技巧和规则| 澳门百家乐官网娱乐城网址| 亚洲百家乐的玩法技巧和规则| 百家乐官网娱乐城会员| 永利博百家乐的玩法技巧和规则| 在线百家乐官网博彩网| 362百家乐的玩法技巧和规则|