Python進(jìn)行圖像處理的入門指南
前言
大家好,最近我在學(xué)習(xí) Python 圖像處理。相比純算法理論,圖像處理最有意思的地方是:代碼運(yùn)行之后馬上就能看到效果,一張圖片經(jīng)過裁剪、縮放、灰度化、濾波、邊緣檢測之后,變化非常直觀。
這篇文章面向 Python 初學(xué)者,按照“基礎(chǔ)概念 → 環(huán)境搭建 → 常用操作 → 實(shí)戰(zhàn)案例 → 完整代碼”的路線,帶大家從零開始完成一次 Python 圖像處理入門實(shí)踐。
本文主要使用兩個(gè)常見庫:
Pillow:適合圖片打開、保存、縮放、裁剪、格式轉(zhuǎn)換等基礎(chǔ)處理OpenCV:適合圖像增強(qiáng)、濾波、邊緣檢測、輪廓識(shí)別等計(jì)算機(jī)視覺任務(wù)
一、圖像處理基礎(chǔ)
1.1 什么是圖像處理
圖像處理就是使用程序?qū)D片進(jìn)行讀取、分析、修改和保存。常見任務(wù)包括:
- 圖片格式轉(zhuǎn)換:例如 PNG 轉(zhuǎn) JPG
- 圖片尺寸調(diào)整:例如生成縮略圖
- 圖片裁剪:截取指定區(qū)域
- 灰度處理:把彩色 圖轉(zhuǎn)換為黑白圖
- 圖像增強(qiáng):調(diào)整亮度、對(duì)比度、銳化
- 邊緣檢測:提取物體輪廓
- 批量處理:一次性處理多個(gè)圖片文件
1.2 圖像在程序中的表示
一張圖片在計(jì)算機(jī)里本質(zhì)上是像素矩陣。
彩色 圖片通常由三個(gè)通道組成:
- R:紅色通道
- G:綠色通道
- B:藍(lán)色通道
在 OpenCV 中,默認(rèn)通道順序是 BGR,不是常見的 RGB,這是初學(xué)者非常容易踩坑的地方。
import cv2
image = cv2.imread("demo.jpg")
print(image.shape)
如果輸出:
(600, 800, 3)
表示圖片高度為 600,寬度為 800,有 3 個(gè)顏色通道。
二、環(huán)境搭建
2.1 安裝依賴庫
在命令提示符或 PowerShell 中執(zhí)行:
pip install pillow opencv-python numpy matplotlib
各庫作用如下:
pillow:基礎(chǔ)圖像讀寫和處理opencv-python:計(jì)算機(jī)視覺處理numpy:矩陣計(jì)算matplotlib:顯示圖片和繪圖
2.2 準(zhǔn)備測試圖片
建議準(zhǔn)備一張普通圖片,例如:
demo.jpg
把圖片和 Python 腳本放在同一個(gè)文件夾中,方便后續(xù)讀取。
目錄結(jié)構(gòu)可以這樣:
image_demo/ ├── demo.jpg └── image_processing_demo.py
三、使用 Pillow 進(jìn)行基礎(chǔ)操作
3.1 打開和保存圖片
from PIL import Image
image = Image.open("demo.jpg")
print(image.size)
print(image.mode)
image.save("output_copy.jpg")
說明:
image.size:圖片尺寸,返回(寬度, 高度)image.mode:圖片模式,例如RGB、RGBA、Lsave():保存圖片
3.2 圖片縮放
from PIL import Image
image = Image.open("demo.jpg")
resized = image.resize((400, 300))
resized.save("output_resized.jpg")
如果想按比例縮放,可以這樣寫:
from PIL import Image
image = Image.open("demo.jpg")
width, height = image.size
new_width = 400
new_height = int(height * new_width / width)
resized = image.resize((new_width, new_height))
resized.save("output_keep_ratio.jpg")
3.3 圖片裁剪
from PIL import Image
image = Image.open("demo.jpg")
box = (100, 100, 500, 400)
cropped = image.crop(box)
cropped.save("output_cropped.jpg")
crop() 的參數(shù)是一個(gè)四元組:
(左, 上, 右, 下)
3.4 灰度轉(zhuǎn)換
from PIL import Image
image = Image.open("demo.jpg")
gray = image.convert("L")
gray.save("output_gray.jpg")
L 表示灰度模式,每個(gè)像素只保留亮度信息。
四、使用 OpenCV 進(jìn)行圖像處理
4.1 讀取和顯示圖片
import cv2
image = cv2.imread("demo.jpg")
cv2.imshow("image", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
注意:
cv2.imread()讀取圖片cv2.imshow()顯示圖片cv2.waitKey(0)等待鍵盤輸入cv2.destroyAllWindows()關(guān)閉窗口
4.2 BGR 轉(zhuǎn) RGB
OpenCV 默認(rèn)使用 BGR。如果要用 matplotlib 顯示,需要轉(zhuǎn)換為 RGB。
import cv2
import matplotlib.pyplot as plt
image = cv2.imread("demo.jpg")
rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
plt.imshow(rgb_image)
plt.axis("off")
plt.show()
4.3 灰度圖
import cv2
image = cv2.imread("demo.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imwrite("opencv_gray.jpg", gray)
4.4 高斯模糊
高斯模糊常用于降噪,讓圖片變得更平滑。
import cv2
image = cv2.imread("demo.jpg")
blurred = cv2.GaussianBlur(image, (7, 7), 0)
cv2.imwrite("opencv_blur.jpg", blurred)
參數(shù) (7, 7) 是卷積核大小,必須是正奇數(shù)。
4.5 邊緣檢測
Canny 邊緣檢測可以提取圖片中的輪廓線。
import cv2
image = cv2.imread("demo.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 100, 200)
cv2.imwrite("opencv_edges.jpg", edges)
其中 100 和 200 是兩個(gè)閾值,閾值不同,邊緣檢測結(jié)果也會(huì)不同。
五、實(shí)戰(zhàn)項(xiàng)目一:批量生成縮略圖
很多網(wǎng)站或后臺(tái)系統(tǒng)都需要生成縮略圖。下面用 Pillow 批量處理一個(gè)文件夾中的圖片。
from pathlib import Path
from PIL import Image
def create_thumbnails(input_dir, output_dir, size=(300, 300)):
input_path = Path(input_dir)
output_path = Path(output_dir)
output_path.mkdir(parents=True, exist_ok=True)
image_exts = [".jpg", ".jpeg", ".png", ".bmp"]
for file_path in input_path.iterdir():
if file_path.suffix.lower() not in image_exts:
continue
image = Image.open(file_path)
image.thumbnail(size)
save_path = output_path / f"{file_path.stem}_thumb.jpg"
image.convert("RGB").save(save_path, quality=90)
print(f"已生成縮略圖:{save_path}")
create_thumbnails("images", "thumbnails")
thumbnail() 會(huì)保持原始比例,不會(huì)強(qiáng)行拉伸圖片。
六、實(shí)戰(zhàn)項(xiàng)目二:批量添加文字水印
在圖片右下角添加文字水印,是非常常見的批處理需求。
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont
def add_text_watermark(image_path, output_path, text):
image = Image.open(image_path).convert("RGBA")
watermark_layer = Image.new("RGBA", image.size, (255, 255, 255, 0))
draw = ImageDraw.Draw(watermark_layer)
font = ImageFont.truetype("arial.ttf", 32)
text_box = draw.textbbox((0, 0), text, font=font)
text_width = text_box[2] - text_box[0]
text_height = text_box[3] - text_box[1]
x = image.width - text_width - 30
y = image.height - text_height - 30
draw.text((x, y), text, font=font, fill=(255, 255, 255, 160))
result = Image.alpha_composite(image, watermark_layer)
result.convert("RGB").save(output_path, quality=95)
def batch_add_watermark(input_dir, output_dir, text):
input_path = Path(input_dir)
output_path = Path(output_dir)
output_path.mkdir(parents=True, exist_ok=True)
for file_path in input_path.glob("*.*"):
if file_path.suffix.lower() not in [".jpg", ".jpeg", ".png"]:
continue
save_path = output_path / f"{file_path.stem}_watermark.jpg"
add_text_watermark(file_path, save_path, text)
print(f"已添加水?。簕save_path}")
batch_add_watermark("images", "watermarked", "Python Image")
如果 arial.ttf 找不到,可以換成 Windows 常見字體路徑:
font = ImageFont.truetype("C:/Windows/Fonts/msyh.ttc", 32)
七、實(shí)戰(zhàn)項(xiàng)目三:圖像邊緣檢測工具
下面做一個(gè)完整的小工具:讀取圖片、灰度化、模糊降噪、邊緣檢測,并把每一步結(jié)果保存下來。
from pathlib import Path
import cv2
def detect_edges(image_path, output_dir):
output_path = Path(output_dir)
output_path.mkdir(parents=True, exist_ok=True)
image = cv2.imread(str(image_path))
if image is None:
raise FileNotFoundError(f"圖片讀取失敗:{image_path}")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
edges = cv2.Canny(blurred, 80, 180)
cv2.imwrite(str(output_path / "01_gray.jpg"), gray)
cv2.imwrite(str(output_path / "02_blurred.jpg"), blurred)
cv2.imwrite(str(output_path / "03_edges.jpg"), edges)
print("處理完成,結(jié)果已保存。")
detect_edges("demo.jpg", "edge_output")
這個(gè)流程適合用來理解很多視覺任務(wù)的前處理步驟。
八、完整代碼演示
下面是一份完整代碼,整合了圖片信息讀取、縮放、裁剪、灰度化、模糊、邊緣檢測、批量縮略圖和水印功能。
保存為 image_processing_demo.py:
from pathlib import Path
import cv2
from PIL import Image, ImageDraw, ImageFont
IMAGE_EXTS = [".jpg", ".jpeg", ".png", ".bmp"]
def show_image_info(image_path):
image = Image.open(image_path)
print("圖片路徑:", image_path)
print("圖片尺寸:", image.size)
print("圖片模式:", image.mode)
print("圖片格式:", image.format)
def resize_keep_ratio(image_path, output_path, new_width=500):
image = Image.open(image_path)
width, height = image.size
new_height = int(height * new_width / width)
resized = image.resize((new_width, new_height))
resized.save(output_path)
def crop_center(image_path, output_path, crop_width=400, crop_height=300):
image = Image.open(image_path)
width, height = image.size
left = (width - crop_width) // 2
top = (height - crop_height) // 2
right = left + crop_width
bottom = top + crop_height
cropped = image.crop((left, top, right, bottom))
cropped.save(output_path)
def convert_to_gray(image_path, output_path):
image = Image.open(image_path)
gray = image.convert("L")
gray.save(output_path)
def opencv_blur_and_edges(image_path, output_dir):
output_path = Path(output_dir)
output_path.mkdir(parents=True, exist_ok=True)
image = cv2.imread(str(image_path))
if image is None:
raise FileNotFoundError(f"圖片讀取失?。簕image_path}")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
edges = cv2.Canny(blurred, 80, 180)
cv2.imwrite(str(output_path / "gray.jpg"), gray)
cv2.imwrite(str(output_path / "blurred.jpg"), blurred)
cv2.imwrite(str(output_path / "edges.jpg"), edges)
def create_thumbnails(input_dir, output_dir, size=(300, 300)):
input_path = Path(input_dir)
output_path = Path(output_dir)
output_path.mkdir(parents=True, exist_ok=True)
for file_path in input_path.iterdir():
if file_path.suffix.lower() not in IMAGE_EXTS:
continue
image = Image.open(file_path)
image.thumbnail(size)
save_path = output_path / f"{file_path.stem}_thumb.jpg"
image.convert("RGB").save(save_path, quality=90)
print(f"縮略圖已保存:{save_path}")
def load_font(size):
font_candidates = [
"C:/Windows/Fonts/msyh.ttc",
"C:/Windows/Fonts/simhei.ttf",
"arial.ttf"
]
for font_path in font_candidates:
if Path(font_path).exists():
return ImageFont.truetype(font_path, size)
return ImageFont.load_default()
def add_text_watermark(image_path, output_path, text):
image = Image.open(image_path).convert("RGBA")
watermark_layer = Image.new("RGBA", image.size, (255, 255, 255, 0))
draw = ImageDraw.Draw(watermark_layer)
font = load_font(32)
text_box = draw.textbbox((0, 0), text, font=font)
text_width = text_box[2] - text_box[0]
text_height = text_box[3] - text_box[1]
x = image.width - text_width - 30
y = image.height - text_height - 30
draw.text((x, y), text, font=font, fill=(255, 255, 255, 160))
result = Image.alpha_composite(image, watermark_layer)
result.convert("RGB").save(output_path, quality=95)
def batch_add_watermark(input_dir, output_dir, text):
input_path = Path(input_dir)
output_path = Path(output_dir)
output_path.mkdir(parents=True, exist_ok=True)
for file_path in input_path.iterdir():
if file_path.suffix.lower() not in [".jpg", ".jpeg", ".png"]:
continue
save_path = output_path / f"{file_path.stem}_watermark.jpg"
add_text_watermark(file_path, save_path, text)
print(f"水印圖片已保存:{save_path}")
def main():
demo_image = Path("demo.jpg")
if not demo_image.exists():
print("請(qǐng)先在當(dāng)前目錄準(zhǔn)備一張 demo.jpg 測試圖片。")
return
Path("output").mkdir(exist_ok=True)
show_image_info(demo_image)
resize_keep_ratio(demo_image, "output/resized.jpg", new_width=500)
crop_center(demo_image, "output/cropped.jpg", crop_width=400, crop_height=300)
convert_to_gray(demo_image, "output/gray.jpg")
opencv_blur_and_edges(demo_image, "output/opencv")
add_text_watermark(demo_image, "output/watermark.jpg", "Python Image")
print("基礎(chǔ)圖像處理完成,結(jié)果在 output 文件夾中。")
if Path("images").exists():
create_thumbnails("images", "output/thumbnails")
batch_add_watermark("images", "output/watermarked", "Python Image")
else:
print("如果需要批量處理,請(qǐng)創(chuàng)建 images 文件夾并放入圖片。")
if __name__ == "__main__":
main()
九、運(yùn)行說明
9.1 安裝依賴
pip install pillow opencv-python numpy matplotlib
9.2 準(zhǔn)備圖片
把一張測試圖片命名為:
demo.jpg
并和代碼文件放在同一個(gè)目錄。
9.3 運(yùn)行程序
python image_processing_demo.py
運(yùn)行后會(huì)生成:
output/
├── resized.jpg
├── cropped.jpg
├── gray.jpg
├── watermark.jpg
└── opencv/
├── gray.jpg
├── blurred.jpg
└── edges.jpg如果你創(chuàng)建了 images 文件夾并放入多張圖片,程序還會(huì)批量生成縮略圖和水印圖。
十、常見問題與解決方案
10.1 cv2.imread 讀取結(jié)果是 None
常見原因:
- 圖片路徑寫錯(cuò)
- 文件名不存在
- 路徑中包含特殊字符
- 圖片文件損壞
建議先用 Path.exists() 判斷文件是否存在。
10.2 OpenCV 顯示顏色不對(duì)
OpenCV 默認(rèn)是 BGR,matplotlib 默認(rèn)按 RGB 顯示,所以需要轉(zhuǎn)換:
rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
10.3 水印中文亂碼或不顯示
通常是字體不支持中文。Windows 下可以使用:
font = ImageFont.truetype("C:/Windows/Fonts/msyh.ttc", 32)
10.4 保存 JPG 時(shí)報(bào)錯(cuò)
如果圖片是 RGBA 模式,直接保存為 JPG 可能報(bào)錯(cuò),需要先轉(zhuǎn)換為 RGB:
image.convert("RGB").save("output.jpg")
十一、圖像處理的應(yīng)用場景
Python 圖像處理可以應(yīng)用在很多實(shí)際場景中:
- 電商圖片批量壓縮、裁剪、水印
- 證件照背景處理
- 文檔掃描件增強(qiáng)
- OCR 文字識(shí)別前處理
- 醫(yī)學(xué)影像預(yù)處理
- 工業(yè)缺陷檢測
- 視頻幀分析
- 機(jī)器學(xué)習(xí)數(shù)據(jù)集清洗和增強(qiáng)
如果繼續(xù)深入,可以學(xué)習(xí):
- OpenCV 輪廓檢測
- 圖像閾值分割
- 形態(tài)學(xué)操作
- 模板匹配
- 人臉檢測
- 圖像分類
- 目標(biāo)檢測
十二、總結(jié)
Python 圖像處理是一個(gè)非常適合通過實(shí)踐學(xué)習(xí)的方向。入門階段建議先掌握 Pillow 和 OpenCV 的基礎(chǔ)用法:
- 使用 Pillow 完成圖片打開、保存、縮放、裁剪、灰度轉(zhuǎn)換和水印
- 使用 OpenCV 完成灰度化、模糊、邊緣檢測等視覺處理
- 使用 pathlib 管理文件路徑
- 把單張圖片處理擴(kuò)展為批量圖片處理
從學(xué)習(xí)路徑上看,可以先做小工具,再做完整項(xiàng)目。比如先寫一個(gè)圖片縮放腳本,再擴(kuò)展成批量壓縮工具;先做邊緣檢測,再擴(kuò)展成輪廓提取和目標(biāo)識(shí)別。
保持學(xué)習(xí),保持輸出。圖像處理并不是只能停留在理論里,只要多動(dòng)手寫代碼,一張普通圖片也可以變成很好的練習(xí)素材。
以上就是Python進(jìn)行圖像處理的入門指南的詳細(xì)內(nèi)容,更多關(guān)于Python進(jìn)行圖像處理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python利用pandas分析學(xué)生期末成績實(shí)例代碼
pandas是數(shù)據(jù)分析師最常用的工具之一,這篇文章主要給大家介紹了關(guān)于python如何利用pandas分析學(xué)生期末成績的相關(guān)資料,文中給出了詳細(xì)的實(shí)現(xiàn)方法,需要的朋友可以參考下2021-07-07
python和shell實(shí)現(xiàn)的校驗(yàn)IP地址合法性腳本分享
這篇文章主要介紹了python和shell實(shí)現(xiàn)的校驗(yàn)IP地址合法性腳本分享,每個(gè)腳本配有執(zhí)行效果圖,需要的朋友可以參考下2014-10-10
ROS系統(tǒng)將python包編譯為可執(zhí)行文件的簡單步驟
本文章講述ROS系統(tǒng)下如何將python編譯為可以執(zhí)行文件,步驟比較簡單,感興趣的朋友跟隨小編一起看看吧2021-07-07
python正則表達(dá)式修復(fù)網(wǎng)站文章字體不統(tǒng)一的解決方法
python正則表達(dá)式修復(fù)網(wǎng)站文章字體不統(tǒng)一的解決方法,需要的朋友可以參考一下2013-02-02
python+OpenCV反投影圖像的實(shí)現(xiàn)示例詳解
這篇文章主要介紹了python+OpenCV反投影圖像的實(shí)現(xiàn)示例詳解,本文通過實(shí)例代碼圖文并茂的形式給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧2025-05-05

