不會吧?不會吧,?不會吧?不會有人忘記我還會寫圖像處理的代碼吧,?別說了,,我知道你忘了,沒關系,,我會在這篇文章寫一些很簡短的代碼實現(xiàn)常見的圖像處理工作(別問為啥寫不長,,能力有限,20行開外就不受控制了),。 Sobel算子:Sobel算子是一種基于圖像梯度的邊緣檢測算法,,可以在x方向和y方向上計算圖像的梯度,,然后將兩個梯度值合并成一個邊緣強度值。通??梢允褂肧obel算子來檢測深度圖像中的水平和垂直邊緣,。Scharr算子是一種改進的Sobel算子,,它使用了更大的卷積核來平滑圖像,并在計算梯度時使用更準確的權重,。Scharr算子在處理低對比度圖像時表現(xiàn)更好,。Laplacian算子:Laplacian算子是一種基于二階微分的邊緣檢測算法,可以檢測出深度圖像中的較強的邊緣,。該算子計算圖像的拉普拉斯變換,,并尋找其中的極值點作為邊緣點,。深度邊緣檢測算法:除了基于梯度或微分的算法,,還有一些專門針對深度圖像的邊緣檢測算法。這些算法通常利用深度圖像的信息來檢測物體表面的變化,,例如深度跳變或斜率變化等,。Canny算子是一種廣泛使用的邊緣檢測算法,它采用了多步驟的邊緣檢測過程,。首先,,使用高斯濾波器平滑圖像,然后計算圖像的梯度和梯度方向,。接下來,,應用非極大值抑制和雙閾值處理來提取邊緣,。最后,,通過連接具有強度邊緣的像素來獲得完整的邊緣,。Canny算子在抑制噪聲和保留真實邊緣方面表現(xiàn)良好,通常被認為是一種比Sobel算子更優(yōu)秀的邊緣檢測算法。如何使用Python實現(xiàn)一個抽幀算法?為啥會有這種東西?原因就是因為圖像幀太多又不需要都處理~import cv2
def extract_frames(video_path, interval): # 打開視頻文件 cap = cv2.VideoCapture(video_path) # 計算視頻總幀數(shù)和幀率 frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) fps = cap.get(cv2.CAP_PROP_FPS) # 計算抽幀間隔 interval_frames = int(interval * fps) # 初始化幀計數(shù)器和關鍵幀列表 count = 0 frames = [] # 逐幀遍歷視頻 while True: ret, frame = cap.read() if not ret: break count += 1 # 如果是關鍵幀,將其添加到關鍵幀列表中 if count % interval_frames == 0: frames.append(frame) # 關閉視頻文件 cap.release() return frames 上述代碼中,,extract_frames()函數(shù)接受視頻文件路徑和抽幀間隔作為輸入?yún)?shù),,返回一個包含關鍵幀的列表,。在函數(shù)內(nèi)部,,首先使用cv2.VideoCapture()函數(shù)打開視頻文件,并使用cv2.CAP_PROP_FRAME_COUNT和cv2.CAP_PROP_FPS獲取視頻總幀數(shù)和幀率,。然后,根據(jù)指定的抽幀間隔計算需要保留的關鍵幀,,在逐幀遍歷視頻時根據(jù)幀計數(shù)器來判斷當前幀是否為關鍵幀,,如果是,則將其添加到關鍵幀列表中,。最后,,使用cap.release()函數(shù)關閉視頻文件。可以使用以下代碼調用extract_frames()函數(shù)來從視頻文件中抽取關鍵幀:frames = extract_frames('video.mp4', 1) # 抽取間隔為1秒的關鍵幀 for frame in frames: cv2.imshow('frame', frame) cv2.waitKey(0) cv2.destroyAllWindows() 上述代碼將抽取間隔設置為1秒,,然后遍歷返回的關鍵幀列表,,使用cv2.imshow()函數(shù)顯示每個關鍵幀,并在用戶按下鍵盤后繼續(xù)顯示下一個關鍵幀,。最后,,使用cv2.destroyAllWindows()函數(shù)關閉所有顯示窗口。讓我們使用一個算子來提取深度圖像的邊緣信息的函數(shù):Sobel算子是一種常用的邊緣檢測算子,,它利用圖像的灰度值變化來檢測邊緣,。import cv2 import numpy as np
def extract_depth_edges(depth_img): # 計算Sobel算子的卷積核 sobelx = cv2.Sobel(depth_img, cv2.CV_64F, 1, 0, ksize=3) sobely = cv2.Sobel(depth_img, cv2.CV_64F, 0, 1, ksize=3) # 計算梯度幅值和方向 grad_mag = np.sqrt(sobelx ** 2 + sobely ** 2) grad_dir = np.arctan2(sobely, sobelx) # 將梯度幅值歸一化到0-255之間 grad_mag_norm = cv2.normalize(grad_mag, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8U) # 將梯度方向轉換為角度 grad_dir_deg = (grad_dir * 180 / np.pi) % 180 # 應用非極大值抑制 grad_mag_nms = cv2.Canny(grad_mag_norm, 100, 200) return grad_mag_nms 上述代碼中,extract_depth_edges()函數(shù)接受深度圖像作為輸入?yún)?shù),,返回提取的邊緣信息,。在函數(shù)內(nèi)部,首先使用cv2.Sobel()函數(shù)計算x和y方向上的Sobel算子的卷積核,,然后計算梯度幅值和方向,。接下來,,將梯度幅值歸一化到0-255之間,并將梯度方向轉換為角度,。最后,,應用非極大值抑制(Canny邊緣檢測算法)來提取邊緣信息,并返回結果,。可以使用以下代碼調用extract_depth_edges()函數(shù)來提取深度圖像的邊緣信息:depth_img = cv2.imread('depth_image.png', cv2.IMREAD_GRAYSCALE) edges = extract_depth_edges(depth_img) cv2.imshow('depth_edges', edges) cv2.waitKey(0) cv2.destroyAllWindows()
上述代碼將讀取深度圖像并將其作為輸入?yún)?shù)傳遞給extract_depth_edges()函數(shù),,然后顯示提取的邊緣信息。有時候會有這樣的需求,,把提取的圖像邊緣保存在一個txt文件中:假設我們已經(jīng)提取了深度圖像的邊緣信息,,存儲在名為edge_img的NumPy數(shù)組中,邊緣值的范圍在0到255之間,。import numpy as np
# 假設我們已經(jīng)提取了深度圖像的邊緣信息,,存儲在名為edge_img的NumPy數(shù)組中
# 將邊緣值縮放到0到1之間 edge_img = edge_img / 255.0
# 將邊緣信息轉換為字符串格式 edge_str = np.array2string(edge_img, separator=',', formatter={'float_kind':lambda x: "%.5f" % x})
# 將字符串寫入txt文件 with open('edge_info.txt', 'w') as f: f.write(edge_str) 在上面的代碼中,我們將邊緣值縮放到0到1之間,,并將其轉換為字符串格式,。我們使用NumPy的array2string函數(shù)將數(shù)組轉換為字符串,并使用逗號作為分隔符,。我們還設置了formatter參數(shù),,將浮點數(shù)的小數(shù)位數(shù)限制為5位。最后,,我們將字符串寫入名為edge_info.txt的txt文件中,。請注意,在讀取txt文件時,,需要使用適當?shù)拇a將字符串轉換回NumPy數(shù)組格式,。接下來把抽幀算法和保存邊緣到txt的函數(shù)寫在一起import cv2 import numpy as np
def extract_edge(frame, threshold): # 使用高斯模糊平滑圖像 blurred = cv2.GaussianBlur(frame, (3, 3), 0) # 轉換為灰度圖像 gray = cv2.cvtColor(blurred, cv2.COLOR_BGR2GRAY) # 使用Canny算法提取邊緣 edges = cv2.Canny(gray, threshold, threshold * 2) return edges
def save_edges_to_txt(edges, filename): # 將邊緣值縮放到0到1之間 edges = edges / 255.0 # 將邊緣信息轉換為字符串格式 edge_str = np.array2string(edges, separator=',', formatter={'float_kind':lambda x: "%.5f" % x}) # 將字符串寫入txt文件 with open(filename, 'w') as f: f.write(edge_str)
# 讀取深度圖像 depth_img = cv2.imread('depth_img.png') # 指定抽幀間隔 interval = 10 # 提取深度圖像邊緣 edges = extract_edge(depth_img, 50) # 抽幀,,保留每隔interval個像素 sampled_edges = edges[::interval, ::interval] # 將邊緣信息保存到txt文件中 save_edges_to_txt(sampled_edges, 'edge_info.txt') 在上面的代碼中,,我們定義了一個extract_edge函數(shù)來提取深度圖像的邊緣,該函數(shù)使用高斯模糊平滑圖像并使用Canny算法提取邊緣,。我們還定義了一個save_edges_to_txt函數(shù),,將邊緣信息保存到txt文件中。在主函數(shù)中,,我們首先讀取深度圖像,,然后指定抽幀間隔。我們使用extract_edge函數(shù)提取深度圖像邊緣,,并使用抽幀算法保留每隔interval個像素,。最后,我們使用save_edges_to_txt函數(shù)將提取的邊緣信息保存到txt文件中。上面鄙人已經(jīng)教了你把圖像轉換成txt的文件,,如何把保存在txt文件里面的邊緣信息恢復成圖像呢,?1.從txt文件中讀取邊緣信息字符串,,并將其轉換為NumPy數(shù)組,。可以使用numpy.loadtxt函數(shù)將文件中的數(shù)據(jù)加載到NumPy數(shù)組中,。2,。根據(jù)邊緣信息數(shù)組的大小創(chuàng)建一個全零的數(shù)組,然后將邊緣信息數(shù)組的值復制到全零數(shù)組的對應位置上,??梢允褂胣umpy.zeros函數(shù)創(chuàng)建全零數(shù)組,并使用numpy.put函數(shù)將邊緣信息數(shù)組的值復制到全零數(shù)組的對應位置上,。3.對全零數(shù)組進行插值操作,,以生成與原始深度圖像相同大小的邊緣圖像??梢允褂胏v2.resize函數(shù)對全零數(shù)組進行插值操作,。4.對插值后的邊緣圖像進行二值化處理,以生成二值圖像,??梢允褂胏v2.threshold函數(shù)對插值后的邊緣圖像進行二值化處理。import cv2 import numpy as np
def load_edges_from_txt(filename, shape): # 從txt文件中讀取邊緣信息 edge_str = np.loadtxt(filename, delimiter=',') # 創(chuàng)建全零數(shù)組 edges = np.zeros(shape) # 將邊緣信息復制到全零數(shù)組的對應位置上 np.put(edges, np.arange(shape[0]*shape[1]), edge_str) # 對全零數(shù)組進行插值操作 edges = cv2.resize(edges, (shape[1], shape[0])) # 對插值后的邊緣圖像進行二值化處理 ret, edges = cv2.threshold(edges, 0, 255, cv2.THRESH_BINARY) return edges
# 讀取深度圖像 depth_img = cv2.imread('depth_img.png') # 獲取深度圖像大小 height, width = depth_img.shape[:2] # 從txt文件中加載邊緣信息,,并恢復成圖像 edges = load_edges_from_txt('edge_info.txt', (height//10, width//10)) # 顯示原始深度圖像和恢復的邊緣圖像 cv2.imshow('depth_img', depth_img) cv2.imshow('edges', edges) cv2.waitKey(0) cv2.destroyAllWindows() 在上面的代碼中,,我們定義了一個load_edges_from_txt函數(shù),該函數(shù)從txt文件中加載邊緣信息,,并將其恢復成圖像,。該函數(shù)首先使用numpy.loadtxt函數(shù)從文件中加載數(shù)據(jù),并將其轉換為NumPy數(shù)組,。然后,,該函數(shù)根據(jù)指定的圖像大小創(chuàng)建一個全零數(shù)組,并使用numpy.put函數(shù)將邊緣信息數(shù)組的值復制到全零數(shù)組的對應位置上,。接下來,,該函數(shù)對全零數(shù)組進行插值操作,并使用cv2.threshold函數(shù)對插值后的邊緣圖像進行二值化處理,,生成二值圖像,。最后一個代碼,把1000x1000的圖像信息轉換到10x10的圖像里面,應該怎么做,?使用圖像縮放操作,。可以使用OpenCV中的cv2.resize函數(shù)對原始圖像進行縮放操作,。該函數(shù)的輸入?yún)?shù)包括原始圖像,、目標圖像大小和插值方法等。import cv2
# 讀取原始圖像 img = cv2.imread('original_image.png') # 縮放圖像 new_img = cv2.resize(img, (10, 10), interpolation=cv2.INTER_AREA) # 顯示原始圖像和縮放后的圖像 cv2.imshow('original', img) cv2.imshow('new', new_img) cv2.waitKey(0) cv2.destroyAllWindows() 在上面的代碼中,,我們使用cv2.imread函數(shù)讀取原始圖像,,然后使用cv2.resize函數(shù)對原始圖像進行縮放操作,將其縮放為10x10的圖像,。在cv2.resize函數(shù)中,,我們將目標圖像大小設置為(10, 10),并將插值方法設置為cv2.INTER_AREA,。最后,,我們使用cv2.imshow函數(shù)顯示原始圖像和縮放后的圖像。代碼沒有測試,,寫20行代碼測雞毛,,應該是錯不了的,祝你Copy的開心,!
|