自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

為什么我的CV模型不好用?沒想到原因竟如此簡單……

新聞 機器學習
機器學習專家 Adam Geitgey 近日發(fā)布了一篇文章探討了這一簡單卻又讓很多人頭痛的問題,并分享了他為解決這一問題編寫的自動圖像旋轉(zhuǎn)程序。

計算機視覺模型表現(xiàn)不佳的原因有很多,比如架構(gòu)設(shè)計缺陷、數(shù)據(jù)集代表性不足、超參數(shù)選擇失誤等。但有一個很簡單的原因卻常常被人們忽略:圖像的方向。機器學習專家 Adam Geitgey 近日發(fā)布了一篇文章探討了這一簡單卻又讓很多人頭痛的問題,并分享了他為解決這一問題編寫的自動圖像旋轉(zhuǎn)程序。

我寫過很多有關(guān)計算機視覺和機器學習項目的內(nèi)容,比如目標識別系統(tǒng)和人臉識別項目。我有一個開源的 Python 人臉識別軟件庫,算得上是 GitHub 上非常受歡迎的十大機器學習庫之一。這也意味著我常常收到關(guān)于 Python 和計算機視覺方面的新人提問。 

为什么我的 CV 模型不好用?没想到原因竟如此简单……

以我的經(jīng)驗,有一個技術(shù)問題比其它任何問題都更容易讓人受挫——倒不是復雜的理論問題或昂貴 GPU 的問題。人們基本上沒意識到,幾乎所有人都是以側(cè)向方式將圖像載入內(nèi)存的,而計算機在檢測側(cè)向圖像中的目標或人臉時的能力可沒那么出色。

數(shù)碼相機如何自動旋轉(zhuǎn)圖像

當你在拍攝照片時,相機會感知你向哪邊傾斜。當你在另一個程序中查看照片時,它們會以正確的方向顯示。

为什么我的 CV 模型不好用?没想到原因竟如此简单……

但棘手的問題在于, 你的相機實際上并沒有在保存到磁盤中的文件中旋轉(zhuǎn)圖像數(shù)據(jù)。因為數(shù)碼相機中的圖像傳感器是逐行讀取的,最終匯集成連續(xù)的像素信息流。這能讓相機更輕松地保存像素數(shù)據(jù),因為不管相機的姿勢如何,像素數(shù)據(jù)總是以同樣的順序保存的。

为什么我的 CV 模型不好用?没想到原因竟如此简单……

實際上,照片能否以正確的方向顯示完全取決于圖像查看器應用。相機在保存圖像數(shù)據(jù)的同時還會保存有關(guān)每張圖片的元數(shù)據(jù)——相機設(shè)置、位置數(shù)據(jù)以及理所應當?shù)南鄼C的旋轉(zhuǎn)角度。圖像查看器應當使用這種信息來正確地顯示圖像。
 
圖像元數(shù)據(jù)最常見的格式是 Exif(Exchangeable image file forma「可交換圖像文件格式」的縮寫)。Exif 格式的元數(shù)據(jù)放在相機保存的 jpeg 文件中。你不能直接從圖像本身讀到這種 Exif 數(shù)據(jù),但可以使用任何知道如何讀取這一數(shù)據(jù)的程序進行讀取。
 
下面是使用 Exiftool 讀取的上面的鵝照片的 Exif 元數(shù)據(jù):

为什么我的 CV 模型不好用?没想到原因竟如此简单……

注意 Orientation(方向)這個數(shù)據(jù)元素。它能指示圖像查看器程序,在屏幕上顯示圖像之前將圖順時針旋轉(zhuǎn) 90 度。如果程序忘記這么做,圖像就會側(cè)向顯示。

为什么我的 CV 模型不好用?没想到原因竟如此简单……

為什么這讓很多 Python 計算機視覺應用表現(xiàn)不佳?

Exif 元數(shù)據(jù)并非 jpeg 文件格式的原生部分。在 TIFF 文件格式使用了這種元數(shù)據(jù)之后,jpeg 文件格式才加入這種元數(shù)據(jù)。其保持了與老一代圖像查看器的后向兼容性,但這也意味著某些程序根本沒有費心去解析 Exif 數(shù)據(jù)。

numpy、scipy、TensorFlow、Keras 等大多數(shù)用于處理圖像數(shù)據(jù)的 Python 庫都將自己視為研究通用數(shù)據(jù)數(shù)組的人的科學工具。所以它們不在乎消費者層面的問題,比如「圖像自動旋轉(zhuǎn)」——即使現(xiàn)在的所有相機拍照需要這種操作。

這差不多意味著,你用任意 Python 庫加載圖像時,都會得到未經(jīng)旋轉(zhuǎn)的原始圖像數(shù)據(jù)。現(xiàn)在猜猜看,當你將側(cè)向的或倒向的圖像輸入人臉識別或目標檢測模型會怎樣?因為你提供了錯誤的數(shù)據(jù),檢測器會提示失敗。

你可能認為這個問題僅限于新手或?qū)W生寫的 Python 腳本,但事實并非如此。即使谷歌的旗艦級 Vision API 演示也沒能正確地處理 Exif 方向:

为什么我的 CV 模型不好用?没想到原因竟如此简单……

谷歌的 Vision API 演示無法旋轉(zhuǎn)標準的手機拍攝的縱向圖像。

盡管谷歌的視覺技術(shù)能成功地檢測出側(cè)向圖像中存在一些動物,但它僅提供了一個不具體的「Animal(動物)」標簽。這是因為模型檢測側(cè)向的鵝要比檢測正向的鵝要困難得多。如果在輸入之前先正確地旋轉(zhuǎn)一下,則谷歌 Vision API 會得到如下的結(jié)果:

为什么我的 CV 模型不好用?没想到原因竟如此简单……

當圖像方向正確時,谷歌的檢測結(jié)果要具體得多——不僅能正確給出「Goose(鵝)」標簽,而且置信度分數(shù)要高得多,這就好多了。
 
如果你能如本演示中的那樣看到圖像是側(cè)向的,那么這個問題要明顯得多。但問題就在于你一般看不到。如今計算機上的一般程序都會以正確旋轉(zhuǎn)后的形式顯示圖像,而不是按照它實際在磁盤上存儲的側(cè)向數(shù)據(jù)的形式。所以當你想了解你的模型不能起效的原因而查看圖像時,圖像查看器會以正確的方向顯示,讓你無從了解你的模型效果差的原因。

为什么我的 CV 模型不好用?没想到原因竟如此简单……

Mac 上的 Finder 總是顯示應用了 Exif 旋轉(zhuǎn)后的圖像,這樣就沒法看到文件中的圖像數(shù)據(jù)實際上是側(cè)向的。

這不可避免地導致人們在 GitHub 上報告問題,說他們使用的開源項目根本不行或模型不夠準確。但事情的本質(zhì)非常簡單——他們輸入了側(cè)向甚至顛倒的圖像!

解決這個問題

解決方案是,每當你用 Python 程序加載圖像時,都執(zhí)行一次 Exif 方向元數(shù)據(jù)檢查,并在有需要時進行旋轉(zhuǎn)。做起來很簡單,不過在網(wǎng)上很難找到能為所有方向正確執(zhí)行旋轉(zhuǎn)的示例代碼。

下面是為任意圖像應用正確的方向后再將其載入 numpy 數(shù)組的代碼:

  1. import PIL.Image  
  2. import PIL.ImageOps  
  3. import numpy as np  
  4.   
  5.   
  6. def exif_transpose(img):  
  7.     if not img:  
  8.         return img  
  9.   
  10.     exif_orientation_tag = 274  
  11.   
  12.     # Check for EXIF data (only present on some files)  
  13.     if hasattr(img, "_getexif") and isinstance(img._getexif(), dict) and exif_orientation_tag in img._getexif():  
  14.         exif_data = img._getexif()  
  15.         orientation = exif_data[exif_orientation_tag]  
  16.   
  17.         # Handle EXIF Orientation  
  18.         if orientation == 1:  
  19.             # Normal image - nothing to do!  
  20.             pass  
  21.         elif orientation == 2:  
  22.             # Mirrored left to right  
  23.             img = img.transpose(PIL.Image.FLIP_LEFT_RIGHT)  
  24.         elif orientation == 3:  
  25.             # Rotated 180 degrees  
  26.             img = img.rotate(180)  
  27.         elif orientation == 4:  
  28.             # Mirrored top to bottom  
  29.             img = img.rotate(180).transpose(PIL.Image.FLIP_LEFT_RIGHT)  
  30.         elif orientation == 5:  
  31.             # Mirrored along top-left diagonal  
  32.             img = img.rotate(-90, expand=True).transpose(PIL.Image.FLIP_LEFT_RIGHT)  
  33.         elif orientation == 6:  
  34.             # Rotated 90 degrees  
  35.             img = img.rotate(-90, expand=True)  
  36.         elif orientation == 7:  
  37.             # Mirrored along top-right diagonal  
  38.             img = img.rotate(90, expand=True).transpose(PIL.Image.FLIP_LEFT_RIGHT)  
  39.         elif orientation == 8:  
  40.             # Rotated 270 degrees  
  41.             img = img.rotate(90, expand=True)  
  42.   
  43.     return img  
  44.   
  45.   
  46. def load_image_file(file, mode='RGB'):  
  47.     # Load the image with PIL  
  48.     img = PIL.Image.open(file)  
  49.   
  50.     if hasattr(PIL.ImageOps, 'exif_transpose'):  
  51.         # Very recent versions of PIL can do exit transpose internally  
  52.         img = PIL.ImageOps.exif_transpose(img)  
  53.     else:  
  54.         # Otherwise, do the exif transpose ourselves  
  55.         img = exif_transpose(img)  
  56.   
  57.     img = img.convert(mode)  
  58.   
  59.     return np.array(img)  

之后,你可以將這個圖像數(shù)據(jù)數(shù)組傳遞給需要的所有標準 Python 機器學習庫,比如 Keras 和 TensorFlow。

因為這個問題很常見,所以我將其制作成了一個 pip 庫,名為 image_to_numpy,你可以這樣安裝它:

  1. pip3 install image_to_numpy 

你可以在任何 Python 程序中使用它來實現(xiàn)正確的圖像加載,比如:

  1. import matplotlib.pyplot as plt 
  2. import image_to_numpy# Load your image file 
  3. img = image_to_numpy.load_image_file("my_file.jpg")# Show it on the screen (or whatever you want to do
  4. plt.imshow(img) 
  5. plt.show() 

 

責任編輯:張燕妮 來源: 機器之心
相關(guān)推薦

2014-10-20 10:53:13

ArubaWi-Fi無線網(wǎng)絡(luò)

2018-11-21 09:11:42

微軟數(shù)據(jù)中心亞馬遜

2018-01-26 23:23:23

JDBC MySQL數(shù)據(jù)庫

2021-01-27 18:13:35

日志nginx信息

2023-12-26 15:10:00

處理二進制文件

2023-10-25 16:36:06

數(shù)字化轉(zhuǎn)型IT系統(tǒng)

2021-05-10 07:35:11

SwaggeYApi部署

2024-01-04 12:33:17

ChatGPTAI視頻

2017-12-26 15:41:26

2014-11-04 10:15:28

Android

2021-08-16 13:44:37

手機電子日本

2019-03-04 14:15:43

微軟Windows日歷

2019-03-08 10:08:41

網(wǎng)絡(luò)程序猿代碼

2022-03-21 08:55:53

RocketMQ客戶端過濾機制

2021-11-29 05:37:24

Windows Def操作系統(tǒng)微軟

2020-08-14 08:19:25

Shell命令行數(shù)據(jù)

2009-04-28 07:48:29

蓋茨打工基金會

2023-10-24 08:01:38

String傳統(tǒng)

2012-12-28 13:47:36

Raspberry PGeek

2017-02-09 17:00:00

iOSSwiftKVC
點贊
收藏

51CTO技術(shù)棧公眾號