
文章來源: 小白學視覺
作者:努比
本期將創建一個類似于Adobe Lightroom的Web應用程序,使用OpenCV和Streamlit實現圖像的卡通化
作為一個狂熱的街頭攝影愛好者,幾乎每個周末都要在城市中拍攝一些照片,因此Adobe Lightroom始終是我們的首選軟件,通過它可以編輯原始照片以使其更具“ Instagram風格”。
我們想能否創建一個自己的圖像編輯軟件?
開源計算機視覺庫(如OpenCV)和開源應用程序框架(如Streamlit)的出現使這一想法得以實現。使用不到100行代碼,我們就可以構建一個簡單的圖像卡通化Web應用程序,模仿Adobe Lightroom的功能。
在本文中,我們將展示如何使用OpenCV和Streamlit,根據濾波器,構建一個簡單的Web應用程序,以將圖像轉換為卡通圖像。
如何使圖像成為卡通圖?
我們通常需要執行兩個主要步驟將圖像轉換為卡通圖像:邊緣檢測和區域平滑。
邊緣檢測的主要目的顯然是為了強調圖像的邊緣,因為卡通圖像通常具有良好的邊緣。同時,區域平滑的主要目的是消除顏色邊界并減少圖像的噪點,使圖像像素化程度降低。
根據不同濾波器,我們可以獲得不同的圖像卡通化結果。在本文中,將有四個不同的過濾器:
1. 鉛筆素描
2. 細節增強
3. 雙邊過濾器
4. 鉛筆邊緣
接下來,我們將展示如何應用每個過濾器,以及從每個過濾器中獲得什么樣的結果。
鉛筆素描濾波器
使用“鉛筆素描”濾波器,您的圖像將被轉換為素描,就像使用鉛筆繪制圖像一樣。下面是使用OpenCV將圖像轉換為鉛筆素描的完整代碼。
# Convert the image into grayscale image gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # Blur the image using Gaussian Blur gray_blur = cv2.GaussianBlur(gray, (25, 25), 0) # Convert the image into pencil sketch cartoon = cv2.divide(gray, gray_blur, scale=250.0)
令人驚訝的是,使用OpenCV,我們只需三行代碼就可以將圖像轉換成鉛筆素描狀的圖片?,F在讓我逐行解釋一下該圖像發生了哪些變化。
在第一行中,我們使用OpenCV的cvtColor()功能將圖像從彩色通道轉換為灰度通道。這很簡單,處理的結果是我們將圖像變成了灰度圖。
接下來,我們使用高斯模糊對圖像進行模糊處理。模糊灰度圖像,實際上是在平滑圖像,減少圖像的噪點。另外,模糊也是我們檢測圖像邊緣的必要步驟。
模糊圖像,可以使用OpenCV中的GaussianBlur()功能。我在GaussianBlur()函數中輸入的(25,25)是內核的大小。
由于我們使用高斯模糊,因此內核中像素值的分布遵循正態分布。核數越大,標準偏差將越大,因此模糊效果越強。下面是內核大小不同時的模糊結果示例。
基于不同內核大小的模糊效果
最后一步是將原始灰度圖像除以模糊后的灰度圖像。這樣可以得出兩個圖像中每個像素之間的變化率。模糊效果越強,每個像素的值相對于其原點的變化就越大,因此,它使我們的鉛筆素描更加清晰。
以下是使用鉛筆素描過濾器的結果。
鉛筆素描過濾器實現示例
細節增強濾波器
簡而言之,“細節增強”濾鏡通過銳化圖像,平滑顏色以及增強邊緣效果為我們提供了卡通效果。以下是使用此濾鏡將您的圖像轉換成卡通的完整代碼。
#convert the image into grayscale image gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #Blur the grayscale image with median blur gray_blur = cv2.medianBlur(gray, 3) #Apply adaptive thresholding to detect edges edges = cv2.adaptiveThreshold(gray_blur, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 9, 9) #Sharpen the image color = cv2.detailEnhance(img, sigma_s=5, sigma_r=0.5) #Merge the colors of same images using "edges" as a mask cartoon = cv2.bitwise_and(color, color, mask=edges)
第一步與之前相同,我們需要將圖像轉換為灰度圖像。
接下來,不使用高斯模糊,而是應用中值模糊。為此,我們使用OpenCV中的medianBlur() 函數。中值模糊通過計算與內核重疊的像素值的中值,然后將其中心像素替換為中值。但是,我們可以根據需要先使用高斯模糊。
接下來,我們需要檢測圖像的邊緣。為此,將自適應閾值與OpenCV中的adaptiveThreshold() 函數一起應用。自適應閾值的主要目標是根據內核重疊的像素的平均值,將圖像每個區域中的每個像素值轉換為黑色或白色。
以下是自適應閾值對模糊圖像的影響的可視化結果。
左:自適應閾值之前—右:自適應閾值之后
為了使圖像看起來更清晰,我們可以使用OpenCV中的detailEnhance()函數。我們需要指定兩個參數:
? sigma_s:控制著鄰域的大小,該鄰域的大小將被加權以替換圖像中的像素值。值越高,鄰域越大。這樣可以使圖像更平滑。
? sigma_r:如果要在平滑圖像時保留邊緣,這很重要。較小的值只會產生非常相似的顏色進行平均(即平滑),而相差很大的顏色將保持不變。
最后,我們使用自適應閾值的結果作為掩碼。然后,根據蒙版的值合并細節增強的結果,以創建具有清晰邊緣的清晰效果。
以下是“細節增強”過濾器的示例結果。
細節增強過濾器實現示例
雙邊過濾器
使用雙邊濾鏡的一大優勢是,我們可以在保留邊緣的同時使圖像和顏色平滑。以下是通過雙邊過濾將您的圖像轉換為卡通圖像的完整代碼。
#convert the image into grayscale image gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #Blur the grayscale image with median blur gray_blur = cv2.medianBlur(gray, 3) #Apply adaptive thresholding to detect edges edges = cv2.adaptiveThreshold(gray_blur, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 9, 9) #Sharpen the image color = cv2.detailEnhance(img, sigma_s=5, sigma_r=0.5) #Merge the colors of same images using "edges" as a mask cartoon = cv2.bitwise_and(color, color, mask=edges)
如果仔細看,所有步驟都與“細節增強”過濾器中的步驟相似,但是這次不是使用detailEnhance() 函數,而是使用openCV中的bilateralFilter()函數。
調用此函數時需要傳遞的參數與detailEnhance()相同,只多一個附加參數,即內核大小d。首先,我們指定圖像源,然后是d,sigma_s和sigma_r值控制平滑效果,并保持邊緣。
以下是使用雙邊過濾器的結果示例。
雙邊過濾器實施示例
鉛筆邊緣濾波器
鉛筆邊緣濾鏡可創建僅包含重要邊緣和白色背景的新圖像。要應用此濾波器,下面是完整的代碼。
#Convert the image into grayscale image gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #Blur the grayscale image using median blur gray = cv2.medianBlur(gray, 25) #Detect edges with Laplacian edges = cv2.Laplacian(gray, -1, ksize=3) #Invert the edges edges_inv = 255-edges #Create a pencil edge sketch dummy, cartoon = cv2.threshold(edges_inv, 150, 255, cv2.THRESH_BINARY)
前兩個步驟與其他過濾器相同。首先,我們將圖像轉換為灰度圖像。接下來,我們使用大小為25的內核對圖像進行模糊處理。
接下來,我們應用拉普拉斯濾波器來檢測邊緣。根據內核的大小,拉普拉斯濾波器中的值可以不同。
Laplacian濾波器的工作是,將通過對象內部的灰度級和圖像背景強度來突出對象的邊緣。以下是拉普拉斯濾波器應用結果。
左:拉普拉斯濾波器應用之前—右:拉普拉斯濾波器應用之后
接下來,我們將Laplacian濾波器的結果求反。最后,通過應用openCV中的threshold()函數,根據指定的閾值將灰度圖像轉換為全黑或全白。
以下是“鉛筆邊緣”過濾器的結果示例。
Pencil Edges濾鏡實現示例
使用Streamlit構建圖像卡通化Web應用程序
在創建了圖像卡通化濾波器的代碼之后,現在就可以創建圖像卡通化Web應用程序了。
第一步,需要將創建圖像卡通化濾波器的所有代碼放入一個函數中,以便于訪問。到目前為止,我們已經對每個參數值進行了硬編碼,例如內核的大小等等。
現在,我們可以讓用戶使用滑塊根據自己的喜好指定一個值,而不是對每個參數值進行硬編碼。為此,我們可以使用Streamlit中的streamlit.slider()函數。下面是其實現的示例。
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) scale_val = st.slider('Tune the brightness of your sketch (the higher the value, the brighter your sketch)', 0.0, 300.0, 250.0) kernel = st.slider('Tune the boldness of the edges of your sketch (the higher the value, the bolder the edges)', 1, 99, 25, step=2) gray_blur = cv2.GaussianBlur(gray, (kernel, kernel), 0) cartoon = cv2.divide(gray, gray_blur, scale= scale_val)
使用此滑塊,可以創建一個交互式圖像卡通化Web應用程序,就像Adobe Lightroom一樣。每次調整內核的值和其他參數時,圖像卡通化的結果都會實時更改和更新。
我們可以將其應用到streamlit.slider()上,創建的每個圖像卡通化濾波器,以替換硬編碼的參數值。
接下來,我們需要添加一個小插件,以便用戶可以上傳自己想要轉換為卡通的圖像。為此,我們可以使用Streamlit中的streamlit.file_uploader()函數。要添加某些文本到Web應用程序中,我們可以使用Streamlit 中的streamlit.text()或streamlit.write()。
用戶上傳圖像后,現在我們需要顯示圖像,使用圖像卡通化濾波器之一編輯圖像,并顯示卡通化圖像,以便用戶知道他們是否要進一步調整滑塊。要顯示圖像,我們可以使用Streamlit中的streamlit.image()函數。
以下是在不到100行代碼的情況下如何構建圖像卡通化Web應用程序的實現。
import cv2 import streamlit as st import numpy as np from PIL import Image def cartoonization (img, cartoon): gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) if cartoon == "Pencil Sketch": value = st.sidebar.slider('Tune the brightness of your sketch (the higher the value, the brighter your sketch)', 0.0, 300.0, 250.0) kernel = st.sidebar.slider('Tune the boldness of the edges of your sketch (the higher the value, the bolder the edges)', 1, 99, 25, step=2) gray_blur = cv2.GaussianBlur(gray, (kernel, kernel), 0) cartoon = cv2.divide(gray, gray_blur, scale=value) if cartoon == "Detail Enhancement": smooth = st.sidebar.slider('Tune the smoothness level of the image (the higher the value, the smoother the image)', 3, 99, 5, step=2) kernel = st.sidebar.slider('Tune the sharpness of the image (the lower the value, the sharper it is)', 1, 21, 3, step =2) edge_preserve = st.sidebar.slider('Tune the color averaging effects (low: only similar colors will be smoothed, high: dissimilar color will be smoothed)', 0.0, 1.0, 0.5) gray = cv2.medianBlur(gray, kernel) edges = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 9, 9) color = cv2.detailEnhance(img, sigma_s=smooth, sigma_r=edge_preserve) cartoon = cv2.bitwise_and(color, color, mask=edges) if cartoon == "Pencil Edges": kernel = st.sidebar.slider('Tune the sharpness of the sketch (the lower the value, the sharper it is)', 1, 99, 25, step=2) laplacian_filter = st.sidebar.slider('Tune the edge detection power (the higher the value, the more powerful it is)', 3, 9, 3, step =2) noise_reduction = st.sidebar.slider('Tune the noise effects of your sketch (the higher the value, the noisier it is)', 10, 255, 150) gray = cv2.medianBlur(gray, kernel) edges = cv2.Laplacian(gray, -1, ksize=laplacian_filter) edges_inv = 255-edges dummy, cartoon = cv2.threshold(edges_inv, noise_reduction, 255, cv2.THRESH_BINARY) if cartoon == "Bilateral Filter": smooth = st.sidebar.slider('Tune the smoothness level of the image (the higher the value, the smoother the image)', 3, 99, 5, step=2) kernel = st.sidebar.slider('Tune the sharpness of the image (the lower the value, the sharper it is)', 1, 21, 3, step =2) edge_preserve = st.sidebar.slider('Tune the color averaging effects (low: only similar colors will be smoothed, high: dissimilar color will be smoothed)', 1, 100, 50) gray = cv2.medianBlur(gray, kernel) edges = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 9, 9) color = cv2.bilateralFilter(img, smooth, edge_preserve, smooth) cartoon = cv2.bitwise_and(color, color, mask=edges) return cartoon ############################################################################### st.write(""" # Cartoonize Your Image! """ ) st.write("This is an app to turn your photos into cartoon") file = st.sidebar.file_uploader("Please upload an image file", type=["jpg", "png"]) if file is None: st.text("You haven't uploaded an image file") else: image = Image.open(file) img = np.array(image) option = st.sidebar.selectbox( 'Which cartoon filters would you like to apply?', ('Pencil Sketch', 'Detail Enhancement', 'Pencil Edges', 'Bilateral Filter')) st.text("Your original image") st.image(image, use_column_width=True) st.text("Your cartoonized image") cartoon = cartoonization(img, option) st.image(cartoon, use_column_width=True)
現在,可以打開提示符,然后轉到包含上面代碼的Python文件的工作目錄。接下來,您需要使用以下命令運行代碼。
streamlit run your_app_name.py
最后,您可以在本地計算機上使用圖像卡通化Web應用程序!以下是該網絡應用程序的示例。
該網絡應用程序示例
部署Web應用
本節是可選的,但是如果小伙伴需要部署Web應用程序以便其他人也可以訪問您的Web應用程序,則可以使用Heroku部署Web應用程序。
要將Web應用程序部署到Heroku,首先要免費創建一個Heroku帳戶,然后下載Heroku CLI。
接下來需要在與Python文件相同的目錄中創建四個其他文件,它們是:
? requirements.txt:這是文本文件,用于告訴Heroku構建Web應用程序需要哪些依賴項。因為在我們的web應用程序,我們使用四種不同的庫:opencv,numpy,Pillow,和streamlit,那么我們就可以寫所有這些庫及其版本為requirements.txt的
opencv-python==4.3.0.36 streamlit==0.63.0 Pillow==7.0.0 numpy==1.18.1
? setup.sh:這是用于在Heroku上設置配置的文件。為此setup.sh文件編寫以下內容。
mkdir -p ~/.streamlit/ echo "\ [server]\n\ headless = true\n\ port = $PORT\n\ enableCORS = false\n\ \n\ " > ~/.streamlit/config.toml
? Procfile:這是告訴Heroku哪些文件以及應如何執行文件的文件。為Procfile編寫以下內容。
web: sh setup.sh && streamlit run cartoon_app.py
? Aptfile:這是Heroku 構建包的文件,以使OpenCV能夠在Heroku中運行。為Aptfile編寫以下內容。
libsm6 libxrender1 libfontconfig1 libice6
接下來,打開命令提示符,然后轉到Python文件和這四個其他文件的工作目錄。在其中鍵入heroku login命令,以便您登錄到Heroku帳戶。
現在,您可以通過鍵入來創建新應用heroku create your-app-name。為確保您位于新創建的應用程序內部,請鍵入以下內容:
heroku git:remote -a your-app-name
接下來,我們需要在新創建的應用程序中添加一個buildpack,以使OpenCV能夠在Heroku上運行。要添加必要的buildpack,請在Heroku CLI上鍵入以下內容。
heroku create --buildpack https://github.com/heroku/heroku-buildpack-apt.git
現在設置好了。接下來,您需要通過打字來初始化一個空的git git init其次是git add .,git commit和git push heroku master命令。
git init git add . git commit -m "Add your messages" git push heroku master
之后,部署過程就開始了,并且可能需要一些時間來等待此部署過程。最后,Heroku將生成新部署的Web應用程序的URL。
就是這樣!現在,我們已經構建了自己的圖像卡通化Web應用程序,該應用程序模仿了Adobe Lightroom的功能。
數據分析咨詢請掃描二維碼
若不方便掃碼,搜微信號:CDAshujufenxi
在本文中,我們將探討 AI 為何能夠加速數據分析、如何在每個步驟中實現數據分析自動化以及使用哪些工具。 數據分析中的AI是什么 ...
2025-05-20當數據遇見人生:我的第一個分析項目 記得三年前接手第一個數據分析項目時,我面對Excel里密密麻麻的銷售數據手足無措。那些跳動 ...
2025-05-20在數字化運營的時代,企業每天都在產生海量數據:用戶點擊行為、商品銷售記錄、廣告投放反饋…… 這些數據就像散落的拼圖,而相 ...
2025-05-19在當今數字化營銷時代,小紅書作為國內領先的社交電商平臺,其銷售數據蘊含著巨大的商業價值。通過對小紅書銷售數據的深入分析, ...
2025-05-16Excel作為最常用的數據分析工具,有沒有什么工具可以幫助我們快速地使用excel表格,只要輕松幾步甚至輸入幾項指令就能搞定呢? ...
2025-05-15數據,如同無形的燃料,驅動著現代社會的運轉。從全球互聯網用戶每天產生的2.5億TB數據,到制造業的傳感器、金融交易 ...
2025-05-15大數據是什么_數據分析師培訓 其實,現在的大數據指的并不僅僅是海量數據,更準確而言是對大數據分析的方法。傳統的數 ...
2025-05-14CDA持證人簡介: 萬木,CDA L1持證人,某電商中廠BI工程師 ,5年數據經驗1年BI內訓師,高級數據分析師,擁有豐富的行業經驗。 ...
2025-05-13CDA持證人簡介: 王明月 ,CDA 數據分析師二級持證人,2年數據產品工作經驗,管理學博士在讀。 學習入口:https://edu.cda.cn/g ...
2025-05-12CDA持證人簡介: 楊貞璽 ,CDA一級持證人,鄭州大學情報學碩士研究生,某上市公司數據分析師。 學習入口:https://edu.cda.cn/g ...
2025-05-09CDA持證人簡介 程靖 CDA會員大咖,暢銷書《小白學產品》作者,13年頂級互聯網公司產品經理相關經驗,曾在百度、美團、阿里等 ...
2025-05-07相信很多做數據分析的小伙伴,都接到過一些高階的數據分析需求,實現的過程需要用到一些數據獲取,數據清洗轉換,建模方法等,這 ...
2025-05-06以下的文章內容來源于劉靜老師的專欄,如果您想閱讀專欄《10大業務分析模型突破業務瓶頸》,點擊下方鏈接 https://edu.cda.cn/g ...
2025-04-30CDA持證人簡介: 邱立峰 CDA 數據分析師二級持證人,數字化轉型專家,數據治理專家,高級數據分析師,擁有豐富的行業經驗。 ...
2025-04-29CDA持證人簡介: 程靖 CDA會員大咖,暢銷書《小白學產品》作者,13年頂級互聯網公司產品經理相關經驗,曾在百度,美團,阿里等 ...
2025-04-28CDA持證人簡介: 居瑜 ,CDA一級持證人國企財務經理,13年財務管理運營經驗,在數據分析就業和實踐經驗方面有著豐富的積累和經 ...
2025-04-27數據分析在當今信息時代發揮著重要作用。單因素方差分析(One-Way ANOVA)是一種關鍵的統計方法,用于比較三個或更多獨立樣本組 ...
2025-04-25CDA持證人簡介: 居瑜 ,CDA一級持證人國企財務經理,13年財務管理運營經驗,在數據分析就業和實踐經驗方面有著豐富的積累和經 ...
2025-04-25在當今數字化時代,數據分析師的重要性與日俱增。但許多人在踏上這條職業道路時,往往充滿疑惑: 如何成為一名數據分析師?成為 ...
2025-04-24以下的文章內容來源于劉靜老師的專欄,如果您想閱讀專欄《劉靜:10大業務分析模型突破業務瓶頸》,點擊下方鏈接 https://edu.cda ...
2025-04-23