摘要
在圖像處理和分析中,前景提取是一項關鍵技術,尤其是在計算機視覺和模式識別領域。本文介紹了一種結合OpenCV和PIL庫的方法,實現在批量處理圖像時有效提取前景并保留原始圖像的EXIF數據。具體步驟包括從指定文件夾中讀取圖像,進行前景提取和處理,然后將結果保存到另一個文件夾,同時保持圖像的元數據信息。
代碼實現步驟
這段代碼實現了從指定文件夾中批量讀取圖像,進行前景提取和處理,并將結果保存到另一個文件夾,同時保留原始圖像的EXIF信息。以下是代碼的詳細解釋:
導入必要的庫
import cv2
import numpy as np
from PIL import Image
import glob
import os
from pathlib import Path
import tqdm
cv2
: OpenCV庫,用于圖像處理。numpy
: 數值計算庫,用于處理數組操作。PIL
: Python圖像庫,用于處理圖像文件和EXIF數據。glob
: 文件名模式匹配庫,用于查找符合特定模式的文件路徑名。os
: 操作系統接口,用于文件和目錄操作。Path
: pathlib庫的一部分,用于處理文件路徑。tqdm
: 進度條庫,用于顯示處理進度。
設置文件夾路徑和創建輸出文件夾
folder_path = r'C:\Users\cdh96\Desktop\iphone11\*.jpg'
output_folder = r'D:\lab\paper\img_preproccess\extrat_foreground\1\images'if not os.path.isdir(output_folder):os.mkdir(output_folder)
folder_path
: 輸入圖像文件夾路徑。output_folder
: 輸出圖像文件夾路徑。如果輸出文件夾不存在,則創建它。
處理圖像
for image_path in tqdm.tqdm(glob.glob(folder_path)):path_obj = Path(image_path)image_path = path_obj.as_posix()img_original = cv2.imread(image_path)if img_original is None:breakimg_original = cv2.cvtColor(img_original, cv2.COLOR_RGB2BGR)img_gray = cv2.imread(image_path, 0)
- 使用
glob
庫獲取所有符合條件的圖像路徑,并使用tqdm
顯示進度條。 - 使用
cv2.imread
讀取圖像,如果圖像為空,退出循環。 - 將圖像轉換為BGR格式,并讀取灰度圖像。
前景提取和處理
output_path = os.path.join(output_folder, path_obj.name)retval, img_global = cv2.threshold(img_gray, 30, 255, cv2.THRESH_BINARY)img_global[img_global > 0] = 1kernel = np.ones((3, 3), dtype=np.uint8)img_global = cv2.morphologyEx(img_global, cv2.MORPH_OPEN, kernel, iterations=4)num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(img_global, connectivity=8)sorted_indices = np.argsort(stats[:, -1])labels[labels != sorted_indices[-2]] = 0labels[labels == sorted_indices[-2]] = 1img_original = img_original * np.repeat(labels[:, :, np.newaxis], 3, axis=-1)img_original = cv2.convertScaleAbs(img_original)image_rgb = cv2.cvtColor(img_original, cv2.COLOR_BGR2RGB)
- 使用全局閾值法提取前景。
- 使用形態學操作去除噪點。
- 使用連通組件分析提取主要前景區域。
- 根據連通組件的面積排序,選取面積第二大的組件作為主要前景。
- 生成前景掩碼并應用到原始圖像。
保存處理后的圖像并保留EXIF數據
cv2.imwrite(output_path, image_rgb)with Image.open(r'D:\lab\paper\img_preproccess\extrat_foreground\1\DSC00421.JPG') as img:exif_data = img.info.get('exif')with Image.open(output_path) as img:img.save(output_path, 'JPEG', exif=exif_data)
- 保存處理后的圖像。
- 從示例圖像中提取EXIF數據,并應用到處理后的圖像中。
這個過程確保了前景的提取和處理,同時保留了原始圖像的EXIF元數據,使得圖像在保存時保留原始的拍攝信息。
整體代碼
import cv2
import numpy as np
from PIL import Image
import glob
import os
from pathlib import Path
import tqdmfolder_path = r'C:\Users\cdh96\Desktop\iphone11\*.jpg'
output_folder = r'D:\lab\paper\img_preproccess\extrat_foreground\1\images'if not os.path.isdir(output_folder):os.mkdir(output_folder)for image_path in tqdm.tqdm(glob.glob(folder_path)):path_obj = Path(image_path)image_path = path_obj.as_posix()img_original = cv2.imread(image_path)if img_original is None:breakimg_original = cv2.cvtColor(img_original, cv2.COLOR_RGB2BGR)img_gray = cv2.imread(image_path, 0)output_path = os.path.join(output_folder,path_obj.name)# 分割retval, img_global = cv2.threshold(img_gray, 30, 255, cv2.THRESH_BINARY)img_global[img_global > 0] = 1# 處理毛刺kernel = np.ones((3, 3), dtype=np.uint8)img_global = cv2.morphologyEx(img_global, cv2.MORPH_OPEN, kernel, iterations=4)# 根據面積選取主體num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(img_global, connectivity=8)sorted_indices = np.argsort(stats[:, -1])# 使用masklabels[labels != sorted_indices[-2]] = 0labels[labels == sorted_indices[-2]] = 1img_original = img_original * np.repeat(labels[:, :, np.newaxis], 3, axis=-1)img_original = cv2.convertScaleAbs(img_original)image_rgb = cv2.cvtColor(img_original, cv2.COLOR_BGR2RGB)cv2.imwrite(output_path, image_rgb)# # 存儲原始的圖像信息with Image.open(r'D:\lab\paper\img_preproccess\extrat_foreground\1\DSC00421.JPG') as img:exif_data = img.info.get('exif')with Image.open(output_path) as img:img.save(output_path, 'JPEG', exif=exif_data)