直方圖均衡化和自適應直方圖均衡化

前言: Hello大家好,我是Dream。 均衡化是數字圖像處理中常用的一種技術,用于增強圖像的視覺效果和對比度。,今天我們將實現對同一張圖像的直方圖均衡化自適應直方圖均衡化處理,學習一下兩者的的基本原理和實現過程,一起來看看吧~

一、直方圖均衡化

直方圖均衡化(Histogram Equalization)是一種圖像處理技術,通過重新分配圖像灰度級別來增強圖像的對比度和視覺效果。它基于整個圖像的灰度直方圖來調整像素的灰度值分布。通過增加較暗區域的亮度和減少較亮區域的亮度,直方圖均衡化可以使圖像的灰度級別分布更均勻,從而增強圖像的細節和對比度。

1.得到灰度圖

通過三同道的彩色圖生成單通道的灰度圖
首先,我們使用PIL庫中的Image.open()函數讀取彩色圖像,并將其轉換為數組。然后,我們獲取圖像的高度和寬度,并創建一個與原始圖像大小相同、數據類型為uint8的全黑數組gray_img,用于保存灰度圖像。

接著,我們遍歷每個像素,將三個通道的值求平均,并將結果保存到灰度圖像中。由于RGB圖像的三個通道具有相同的權重,因此將三個通道的值求平均可以得到一個比較準確的灰度值。

然后,我們將灰度圖像轉換為PIL圖像對象,并使用Matplotlib庫中的plt.imshow()函數顯示彩色圖像和灰度圖像。最后,我們使用PIL庫中的Image.save()函數將灰度圖像保存為文件。

import numpy as np
import cv2
from PIL import Image
import matplotlib.pyplot as plt# 讀取彩色圖像
img = Image.open('image.jpg')# 將圖像轉換為數組
img_arr = np.array(img)# 獲取圖像的高度和寬度
h, w, _ = img_arr.shape# 創建一個新的數組,用于保存灰度圖像
gray_img = np.zeros((h, w), dtype=np.uint8)# 遍歷每個像素,將三個通道的值求平均,并保存到灰度圖像中
for i in range(h):for j in range(w):gray_img[i, j] = int(np.mean(img_arr[i, j]))# 將灰度圖像轉換為PIL圖像對象
gray_pil_img = Image.fromarray(gray_img)
plt.imshow(img)
plt.title('imge')
plt.axis('off')
plt.show()
plt.imshow(gray_pil_img, cmap='gray')
plt.title('gray_pil_imge')
plt.axis('off')
plt.show()
# 保存灰度圖像
gray_pil_img.save('gray_image.jpg')

在這里插入圖片描述
在這里插入圖片描述

2. 直方圖統計

使用PIL庫中的Image.open()函數讀取灰度圖像,并使用convert('L')方法將圖像轉換為灰度模式。然后,我們獲取圖像的寬度和高度,并創建一個長度為256的全0列表hist,用于保存直方圖統計結果。

接著,遍歷每個像素,獲取其灰度值,并將對應的直方圖計數器加1。最后,我們輸出直方圖統計結果,即每個灰度值出現的像素數。

# 讀取灰度圖像
gray_img = Image.open('gray_image.jpg').convert('L')
width, height = gray_img.size# 統計直方圖
hist = [0] * 256
for y in range(height):for x in range(width):pixel = gray_img.getpixel((x, y))hist[pixel] += 1
print(hist)
# 輸出直方圖統計結果
for i in range(len(hist)):print("灰度值 %d: %d 個像素" % (i, hist[i]))

在這里插入圖片描述

3. 繪制直方圖

# 繪制直方圖
plt.bar(range(256), hist)
plt.show()

在這里插入圖片描述

4. 直方圖均衡化

使圖片有更好的視覺效果,有更高的對比度,即像素的灰度分布更平均
首先,我們使用PIL庫中的histogram()函數對灰度圖像進行直方圖統計,得到一個長度為256的列表equ_img,其中每個元素表示對應灰度級別的像素數量。

接著,我們創建一個空列表lut,用于保存灰度級別的映射表。然后,通過遍歷equ_img列表,將每個灰度級別的像素數量除以255得到一個步長step,表示每個灰度級別在均衡化后的直方圖中所占的比例。接下來,我們定義一個變量n,初始化為0,用于記錄當前累積的像素數量。

在內層循環中,我們遍歷256個灰度級別,并將當前累積的像素數量除以步長step得到一個映射值n / step。這個映射值表示當前灰度級別在均衡化后的直方圖中所對應的灰度級別。

最后,我們使用PIL庫中的point()方法,根據映射表lut將灰度圖像進行映射,得到均衡化后的圖像equ_img。在這里,lut列表中的值被用作灰度級別的映射,'L'參數表示輸出圖像的模式為灰度模式。

這樣,經過直方圖均衡化處理后,圖像的灰度分布將更加均勻,增強了圖像的對比度和細節。

# 直方圖均衡化
equ_img = gray_img.histogram()
lut = []
for b in range(0, len(equ_img), 256):step = sum(equ_img[b:b+256]) / 255n = 0for i in range(256):lut.append(n / step)n += equ_img[b+i]
equ_img = gray_img.point(lut, 'L')# 顯示原始圖像和均衡化后的圖像
plt.imshow(gray_img, cmap='gray')
plt.title('Original Image')
plt.axis('off')
plt.show()plt.imshow(equ_img, cmap='gray')
plt.title('Equalized Image')
plt.axis('off')
plt.show()# 保存原始圖像和均衡化后的圖像
gray_img.save('Original.jpg')
equ_img.save('Equalized.jpg')# 統計均衡化后的直方圖
hist_equ = equ_img.histogram()# 繪制均衡化前后的直方圖
plt.hist(gray_img.histogram(), 256, [0, 256])
plt.title('Original Image')
plt.xlim([0, 256])
plt.show()plt.hist(hist_equ, 256, [0, 256])
plt.title('Equalized Image')
plt.xlim([0, 256])
plt.show()

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

二、自適應直方圖均衡化

自適應直方圖均衡化(Adaptive Histogram Equalization)是直方圖均衡化的一種變體,它考慮到圖像中不同區域的局部差異。與直方圖均衡化不同,自適應直方圖均衡化將圖像分成多個小塊,并在每個小塊內獨立地應用直方圖均衡化。通過這種方式,自適應直方圖均衡化可以更好地保留圖像的細節,并避免過度增強噪聲。自適應直方圖均衡化可以根據圖像的局部特征自動調整每個小塊的灰度級別,以實現更精細的圖像增強。

1.自適應直方圖均衡化(AHE)

AHE是一種局部直方圖均衡化方法,它將圖像分成若干個小區域,對每個小區域進行直方圖均衡化處理,從而增強圖像的對比度。該算法的核心思想是在每個小區域內計算直方圖,并將其變換為累積分布函數(CDF),然后將CDF拉伸以增加對比度。因此,AHE可以有效地增強圖像中的局部細節信息。
在此處,我們的輸入參數包括原始圖像img和窗口大小window_size。首先,函數遍歷每個像素,獲取以該像素為中心的大小為window_size的窗口。如果窗口越界,則跳過該像素。然后,計算窗口的直方圖,并計算其累積分布函數。接著,將CDF歸一化并拉伸,以增加窗口內像素的對比度。最后,將均衡化后的像素值放回原圖中,得到均衡化后的結果。

# 自適應直方圖均衡化(AHE)
def adaptive_histogram_equalization(img, window_size):# 獲取圖像大小height, width = img.shape[:2]# 創建一個全黑的圖像result = np.zeros((height, width), dtype=np.uint8)# 遍歷每個像素for i in range(height):for j in range(width):# 獲取窗口中心點center_x, center_y = i + window_size // 2, j + window_size // 2# 如果窗口越界,則跳過if center_x < window_size // 2 or center_x >= height - window_size // 2 or center_y < window_size // 2 or center_y >= width - window_size // 2:continue# 獲取窗口window = img[center_x - window_size // 2:center_x + window_size // 2 + 1, center_y - window_size // 2:center_y + window_size // 2 + 1]# 計算窗口的直方圖hist, _ = np.histogram(window.ravel(), 256, [0, 256])# 計算累積分布函數cdf = hist.cumsum()# 歸一化cdf_normalized = cdf * 255 / cdf[-1]# 將均衡化后的像素值放回原圖中result[i][j] = cdf_normalized[img[i][j]]return result

2.限制對比度自適應直方圖均衡化(CRHE)

CRHE是在AHE的基礎上增加了對比度限制。它通過在AHE之后對像素值進行限制,以避免過度增加對比度而導致噪聲的出現。該算法的核心思想是先使用AHE增強圖像的對比度,然后使用限制對比度的方法對像素值進行截斷,從而控制對比度的增加。
在代碼中,輸入參數包括原始圖像img、窗口大小window_size和對比度限制因子clip_limit。首先,調用自己實現的自適應直方圖均衡化函數adaptive_histogram_equalization對原始圖像進行直方圖均衡化處理,得到均衡化后的結果。接著,使用OpenCV庫中的cv2.createCLAHE函數創建一個限制對比度的CLAHE對象,并將均衡化后的圖像作為輸入進行處理。

# 限制對比度自適應直方圖均衡化(CRHE)
def contrast_limited_adaptive_histogram_equalization(img, window_size, clip_limit):# 使用自己實現的自適應直方圖均衡化ahe_img = adaptive_histogram_equalization(img, window_size)# 使用OpenCV庫實現限制對比度自適應直方圖均衡化clahe = cv2.createCLAHE(clipLimit=clip_limit, tileGridSize=(window_size, window_size))result = clahe.apply(ahe_img)return result

3.讀取圖片

# 讀取圖片
img = cv2.imread("image.jpg", cv2.IMREAD_GRAYSCALE)

4.自適應直方圖均衡化

首先創建一個與原始圖像img相同大小的全黑圖像ahe_result,用于保存處理后的結果。然后,使用一個循環遍歷多個窗口尺寸,依次調用自適應直方圖均衡化函數adaptive_histogram_equalization對原始圖像進行處理,并將處理后的結果加到ahe_result中。最后得到多個尺寸的均衡化結果的平均值,作為最終的均衡化結果。

我們使用了不同尺寸的窗口,分別為50、100、150和200。最后將這四個結果取平均值作為最終結果,這種方法可以提高均衡化的效果,因為不同尺寸的窗口可以捕捉到圖像中不同尺度的局部細節信息,從而增強圖像的對比度和細節信息,避免過大或過小的窗口對結果產生較大影響。

# 自適應直方圖均衡化
# 創建一個和原始圖像大小相同的全零數組ahe_result,用于存儲最終的自適應直方圖均衡化結果ahe_result = np.zeros_like(img)# 遍歷不同的窗口大小,從50到200,步長為50
for window_size in range(50, 201, 50):# 對原始圖像img進行自適應直方圖均衡化操作,使用當前窗口大小window_sizeahe_img = adaptive_histogram_equalization(img, window_size)# 將每次處理后的圖像ahe_img累加到ahe_result中ahe_result += ahe_img# 將ahe_result除以4取整,得到最終的自適應直方圖均衡化結果
ahe_result //= 4

5.限制對比度自適應直方圖均衡化

首先創建一個與原始圖像img相同大小的全黑圖像crhe_result,用于保存處理后的結果。然后,使用一個循環遍歷多個窗口尺寸,依次調用限制對比度自適應直方圖均衡化函數對原始圖像進行處理,并將處理后的結果加到crhe_result中。在本例中,設置對比度限制因子clip_limit為2.0。
我們使用了不同尺寸的窗口,分別為50、100、150和200。最后將這四個結果取平均值作為最終結果,避免過大或過小的窗口對結果產生較大影響。

# 限制對比度自適應直方圖均衡化
# 創建一個和原始圖像大小相同的全零數組crhe_result,用于存儲最終的限制對比度自適應直方圖均衡化結果crhe_result = np.zeros_like(img)# 遍歷不同的窗口大小,從50到200,步長為50
for window_size in range(50, 201, 50):# 對原始圖像img進行限制對比度自適應直方圖均衡化操作,使用當前窗口大小window_size和對比度限制參數2.0crhe_img = contrast_limited_adaptive_histogram_equalization(img, window_size, 2.0)# 將每次處理后的圖像crhe_img累加到crhe_result中crhe_result += crhe_img# 將crhe_result除以4取整,得到最終的限制對比度自適應直方圖均衡化結果
crhe_result //= 4

6.可視化顯示結果

# 顯示結果
fig, ax = plt.subplots(nrows=1, ncols=3, figsize=(12, 8))
ax[0].imshow(img, cmap='gray')
ax[0].set_title('Original1 Image')
ax[1].imshow(ahe_result, cmap='gray')
ax[1].set_title('AHE1 Image')
ax[2].imshow(crhe_result, cmap='gray')
ax[2].set_title('CRHE1 Image')
plt.show()

在這里插入圖片描述

三、對比總結

直方圖均衡化(Histogram Equalization)和自適應直方圖均衡化(Adaptive Histogram Equalization)都是用于圖像增強的技術,目的是改善圖像的對比度和視覺效果。它們的主要區別在于處理圖像的方式和局部性

直方圖均衡化是一種全局的方法,它基于整個圖像的灰度直方圖來調整像素的灰度值分布。通過使灰度級別在圖像中更均勻地分布,直方圖均衡化可以增強圖像的對比度和細節。它使用累積分布函數將原始圖像中的灰度級別映射到一個新的灰度范圍,從而實現圖像的均衡化。

然而,直方圖均衡化是一種全局的方法,它沒有考慮到圖像中不同區域的局部差異。這可能會導致圖像的某些區域過度增強或細節丟失的問題。為了解決這個問題,自適應直方圖均衡化應運而生。

自適應直方圖均衡化是一種局部的方法,在處理圖像時會考慮到不同區域的灰度分布情況。它將圖像分成許多小區域,對每個區域獨立地應用直方圖均衡化。通過這種方式,自適應直方圖均衡化可以更好地保留圖像細節,并避免過度放大噪聲。

自適應直方圖均衡化的一種常見變體是自適應直方圖均衡化(CLAHE),它在每個小區域中使用對比度限制來防止過度放大噪聲。CLAHE的核心思想是將圖像分成許多小塊,然后對每個小塊進行局部直方圖均衡化,并對像素值進行裁剪以限制對比度的增強程度。通過這種方式,CLAHE在增強圖像細節的同時有效控制了噪聲的增強。

總而言之,直方圖均衡化是一種全局的方法,通過整個圖像的灰度直方圖來增強圖像對比度。自適應直方圖均衡化是一種局部的方法,通過對圖像的小塊進行獨立的直方圖均衡化來增強圖像,并通過對比度限制來控制噪聲的放大

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/42402.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/42402.shtml
英文地址,請注明出處:http://en.pswp.cn/news/42402.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MFC中的窗體繪制事件函數:OnCtlColor、OnPaint、OnNcPaint、OnDrawItem、OnEraseBkgnd、OnDraw

文章目錄 CWnd::OnCtlColorCWnd::OnPaintCWnd::OnNcPaintCWnd::OnDrawItemCWnd::OnEraseBkgndCWnd::InvalidateRectCView::OnDraw 參考&#xff1a;https://learn.microsoft.com/ CWnd::OnCtlColor 即將繪制子控件時&#xff0c;框架會調用此成員函數。 afx_msg HBRUSH OnCt…

React 高階組件(HOC)

React 高階組件(HOC) 高階組件不是 React API 的一部分&#xff0c;而是一種用來復用組件邏輯而衍生出來的一種技術。 什么是高階組件 高階組件就是一個函數&#xff0c;且該函數接受一個組件作為參數&#xff0c;并返回一個新的組件。基本上&#xff0c;這是從 React 的組成…

Mongodb 更新集合的方法到底有幾種 (中) ?

更新方法 Mongodb 使用以下幾種方法來更新文檔 &#xff0c; Mongodb V5.0 使用 mongosh 客戶端&#xff1a; db.collection.updateOne(<filter>, <update>, <options>) db.collection.updateMany(<filter>, <update>, <options>) db.c…

docker 安裝elasticsearch、kibana

下載es鏡像 docker pull elasticsearch 啟動es容器 docker run --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.typesingle-node" -e ES_JAVA_OPTS"-Xms512m -Xmx512m" -d elasticsearch 驗證es界面訪問 ?????http://節點ip:9200/ ?…

client-go實戰之十二:選主(leader-election)

歡迎訪問我的GitHub 這里分類和匯總了欣宸的全部原創(含配套源碼)&#xff1a;https://github.com/zq2599/blog_demos 本篇概覽 本文是《client-go實戰》系列的第十二篇&#xff0c;又有一個精彩的知識點在本章呈現&#xff1a;選主(leader-election)在解釋什么是選主之前&…

【自用】云服務器 docker 環境下 HomeAssistant 安裝 HACS 教程

一、進入 docker 中的 HomeAssistant 1.查找 HomeAssistant 的 CONTAINER ID 連接上云服務器&#xff08;宿主機&#xff09;后&#xff0c;終端內進入 root &#xff0c;輸入&#xff1a; docker ps找到了 docker 的 container ID 2.config HomeAssistant 輸入下面的命令&…

修改el-table行懸停狀態的背景顏色

.content:deep().el-table tr:hover>td {background-color: #f5f5f5 !important; /* 設置懸停時的背景顏色 */ }/*這一點很重要&#xff0c;否則可能會導致hover行時操作列還是原來的背景色*/ .content:deep().el-table__body tr.hover-row>td{background-color: #f5f5f5…

使用Nacos配置中心動態管理Spring Boot應用配置

&#x1f337;&#x1f341; 博主貓頭虎 帶您 Go to New World.?&#x1f341; &#x1f984; 博客首頁——貓頭虎的博客&#x1f390; &#x1f433;《面試題大全專欄》 文章圖文并茂&#x1f995;生動形象&#x1f996;簡單易學&#xff01;歡迎大家來踩踩~&#x1f33a; &a…

Linux權限系列--給普通用戶添加某個命令的sudo權限

原文網址&#xff1a;Linux權限系列--給普通用戶添加某個命令的sudo權限_IT利刃出鞘的博客-CSDN博客 簡介 說明 本文介紹Linux系統如何給普通用戶添加某個命令的sudo權限。 使用場景 普通開發者可能需要sudo的命令&#xff1a; apt-get&#xff08;經常要安裝軟件&#x…

【Vue2】---->VueX 3 核心概念

官網&#xff1a; Vuex 是什么&#xff1f; | Vuex (vuejs.org) 目錄 介紹 1、安裝 2、新建 store/index.js 專門存放 vuex 3、 在 main.js 中導入掛載到 Vue 實例上 核心概念 1、核心概念 -state 狀態 1、訪問Vuex中的數據 2、通過$store訪問的語法 3、通過輔助函…

Java IO流(一)IO基礎

概述 IO流本質 I/O表示Input/Output,即數據傳輸過程中的輸入/輸出,并且輸入和輸出都是相對于內存來講Java IO(輸入/輸出)流是Java用于處理數據讀取和寫入的關鍵組件常見的I|O介質包括 文件(輸入|輸出)網絡(輸入|輸出)鍵盤(輸出)顯示器(輸出)使用場景 文件拷貝&#xff08;File&…

Python自帶的IDLE有什么用

在Python的官方解釋器中&#xff0c;自帶了一個名為IDLE(Interactive DeveLopment Environment)的集成開發環境。 一、簡化代碼調試過程 很多初學者在編寫Python代碼時&#xff0c;經常會遇到一些問題需要調試。而在IDLE中&#xff0c;我們可以通過設置斷點、單步調試等方法&…

算法競賽入門【碼蹄集新手村600題】(MT1160-1180)C語言

算法競賽入門【碼蹄集新手村600題】(MT1160-1180&#xff09;C語言 目錄MT1161 N的零MT1162 數組最大公約數MT1163 孿生質數MT1164 最大數字MT1165 卡羅爾數MT1166 自守數MT1167自守數IIMT1168 階乘數MT1169 平衡數MT1170 四葉玫瑰數MT1171 幻數MT1172 完美數字MT1173 魔數MT11…

es線上處理命令記錄

常用命令 搜索 GET _search {"query": {"match_all": {}} }獲取全部模版 GET _index_template GET _index_template/yst_crawler_template獲取全部索引 GET /_cat/indices?v 獲取當前mapping GET /yst_crawler/_mapping創建一個mapping PUT /yst_c…

WebGL游戲站優化實錄【myshmup.com】

myshmup.com 允許在瀏覽器中創建 shmup&#xff08;射擊&#xff09;游戲。 你可以使用具有創意通用許可證的資源或上傳自己的藝術作品和聲音。 創建的游戲可以在網站上發布。 該平臺不需要編碼&#xff0c;游戲對象的配置是在用戶界面的幫助下執行的。 后端是使用Django框架開…

機器學習筆記 - 使用 ResNet-50 和余弦相似度的基于圖像的推薦系統

一、簡述 這里的代碼主要是基于圖像的推薦系統,該系統利用 ResNet-50 深度學習模型作為特征提取器,并采用余弦相似度來查找給定輸入圖像的最相似嵌入。 該系統旨在根據所提供圖像的視覺內容為用戶提供個性化推薦。 二、所需環境 Python 3.x tensorflow ==2.5.0 numpy==1.21.…

星際爭霸之小霸王之小蜜蜂(三)--重構模塊

目錄 前言 一、為什么要重構模塊 二、創建game_functions 三、創建update_screen() 四、修改alien_invasion模塊 五、課后思考 總結 前言 前兩天我們已經成功創建了窗口&#xff0c;并將小蜜蜂放在窗口的最下方中間位置&#xff0c;本來以為今天將學習控制小蜜蜂&#xff0c;結…

GPT-4一紙重洗:從97.6%降至2.4%的巨大挑戰

斯坦福大學和加州大學伯克利分校合作進行的一項 “How Is ChatGPTs Behavior Changing Over Time?” 研究表明&#xff0c;隨著時間的推移&#xff0c;GPT-4 的響應能力非但沒有提高&#xff0c;反而隨著語言模型的進一步更新而變得更糟糕。 研究小組評估了 2023 年 3 月和 20…

win10安裝mysql和c++讀取調用舉例

一、下載mysql8.rar解壓到C盤(也可以解壓到其他位置) 在系統環境變量添加JAVA_HOMEC:\myslq8&#xff0c;并在path中添加%JAVA_HOME%\bin; 二、以管理員身份進入命令窗口 三、修改配置文件指定安裝路徑和數據庫的存放路徑 四、鍵入如下命令初始化并啟動mysql服務,然后修改登錄…

Rust之泛型、trait與生命周期

泛型是具體類型或其他屬性的抽象替代。在編寫代碼時&#xff0c;可以直接描述泛型的行為&#xff0c;或者它與其他泛型產生的聯系&#xff0c;而無須知曉它在編譯和運行代碼時采用的具體類型。 1、泛型數據類型&#xff1a; 們可以在聲明函數簽名或結構體等元素時使用泛型&am…