問題描述
使用以下代碼,我可以刪除圖像中的水平線.見下面的結果.
導入 cv2從 matplotlib 導入 pyplot 作為 pltimg = cv2.imread('image.png',0)拉普拉斯= cv2.拉普拉斯(img,cv2.CV_64F)sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5)plt.subplot(2,2,1),plt.imshow(img,cmap = '灰色')plt.title('Original'), plt.xticks([]), plt.yticks([])plt.subplot(2,2,2),plt.imshow(拉普拉斯,cmap = '灰色')plt.title('拉普拉斯'), plt.xticks([]), plt.yticks([])plt.subplot(2,2,3),plt.imshow(sobelx,cmap = '灰色')plt.title('Sobel X'), plt.xticks([]), plt.yticks([])plt.show()
結果還不錯,不是很完美,但是很好.我想要實現的是
我的一個問題是:如何在不應用灰色效果的情況下保存 Sobel X
?作為原始但經過處理..
另外,有沒有更好的方法呢?
編輯
對源圖像使用以下代碼很好.效果很好.
導入 cv2將 numpy 導入為 npimg = cv2.imread("image.png")img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)img = cv2.bitwise_not(img)th2 = cv2.adaptiveThreshold(img,255, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,15,-2)cv2.imshow("th2", th2)cv2.imwrite("th2.jpg", th2)cv2.waitKey(0)cv2.destroyAllWindows()水平 = th2垂直 = th2行,列 = 水平形狀#反轉圖像,使線條為黑色以進行遮罩Horizo??ntal_inv = cv2.bitwise_not(水平)#perform bitwise_and 用提供的掩碼掩碼行masked_img = cv2.bitwise_and(img, img, mask=horizo??ntal_inv)#反轉圖像恢復正常masked_img_inv = cv2.bitwise_not(masked_img)cv2.imshow("屏蔽的圖像", masked_img_inv)cv2.imwrite("result2.jpg", masked_img_inv)cv2.waitKey(0)cv2.destroyAllWindows()水平尺寸 = int(cols/30)水平結構 = cv2.getStructuringElement(cv2.MORPH_RECT, (horizo??ntalsize,1))水平= cv2.erode(水平,水平結構,(-1,-1))水平 = cv2.擴張(水平,水平結構,(-1,-1))cv2.imshow(水平",水平)cv2.imwrite("horizo??ntal.jpg", 水平)cv2.waitKey(0)cv2.destroyAllWindows()垂直尺寸 = int(行數/30)verticalStructure = cv2.getStructuringElement(cv2.MORPH_RECT, (1, verticalsize))垂直= cv2.erode(垂直,垂直結構,(-1,-1))垂直= cv2.dilate(垂直,垂直結構,(-1,-1))cv2.imshow(垂直",垂直)cv2.imwrite("vertical.jpg", 垂直)cv2.waitKey(0)cv2.destroyAllWindows()垂直 = cv2.bitwise_not(垂直)cv2.imshow("vertical_bitwise_not", 垂直)cv2.imwrite("vertical_bitwise_not.jpg", 垂直)cv2.waitKey(0)cv2.destroyAllWindows()#步驟1邊緣 = cv2.adaptiveThreshold(垂直,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,3,-2)cv2.imshow(邊緣",邊緣)cv2.imwrite("edges.jpg", 邊緣)cv2.waitKey(0)cv2.destroyAllWindows()#第2步kernel = np.ones((2, 2), dtype = "uint8")擴張= cv2.擴張(邊緣,內核)cv2.imshow(擴張",擴張)cv2.imwrite(擴張的.jpg",擴張)cv2.waitKey(0)cv2.destroyAllWindows()# 第三步平滑 = vertical.copy()#步驟4平滑 = cv2.blur(平滑,(4,4))cv2.imshow("平滑", 平滑)cv2.imwrite("smooth.jpg", 平滑)cv2.waitKey(0)cv2.destroyAllWindows()#步驟 5(行,列)= np.where(img == 0)垂直[行,列] = 平滑[行,列]cv2.imshow("vertical_final", 垂直)cv2.imwrite("vertical_final.jpg", 垂直)cv2.waitKey(0)cv2.destroyAllWindows()
但是如果我有這張圖片呢?
我嘗試執行上面的代碼,結果真的很差……
我正在處理的其他圖像是這些......
這是一種方法
將圖像轉換為
image = cv2.imread('1.png')灰色 = cv2.cvtColor(圖像,cv2.COLOR_BGR2GRAY)thresh = cv2.threshold(灰色, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
接下來我們創建一個特殊的水平內核來檢測水平線.我們將這些線條繪制到蒙版上,然后在蒙版上找到輪廓.為了去除線條,我們用白色填充輪廓
檢測到的線
面具
填充輪廓
# 刪除水平水平內核 = cv2.getStructuringElement(cv2.MORPH_RECT, (25,1))檢測到的線= cv2.morphologyEx(thresh,cv2.MORPH_OPEN,horizo??ntal_kernel,迭代=2)cnts = cv2.findContours(detected_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)cnts = cnts[0] 如果 len(cnts) == 2 否則 cnts[1]對于 cnts 中的 c:cv2.drawContours(圖像,[c],-1,(255,255,255),2)
圖像當前有間隙.為了解決這個問題,我們構建了一個垂直內核來修復圖像
# 修復圖片repair_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,6))結果 = 255 - cv2.morphologyEx(255 - 圖像,cv2.MORPH_CLOSE,repair_kernel,迭代 = 1)
<塊引用>
注意根據映像,內核的大小會有所變化.例如,為了檢測更長的行,我們可以使用
(50,1)
內核.如果我們想要更粗的線條,我們可以增加第二個參數為(50,2)
.這是其他圖片的結果
檢測到的線
原始(左),刪除(右)
檢測到的線
原始(左),刪除(右)
完整代碼
導入 cv2圖像 = cv2.imread('1.png')灰色 = cv2.cvtColor(圖像,cv2.COLOR_BGR2GRAY)thresh = cv2.threshold(灰色, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]# 刪除水平水平內核 = cv2.getStructuringElement(cv2.MORPH_RECT, (25,1))檢測到的線= cv2.morphologyEx(thresh,cv2.MORPH_OPEN,horizo??ntal_kernel,迭代=2)cnts = cv2.findContours(detected_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)cnts = cnts[0] 如果 len(cnts) == 2 否則 cnts[1]對于 cnts 中的 c:cv2.drawContours(圖像,[c],-1,(255,255,255),2)# 修復圖像repair_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,6))結果 = 255 - cv2.morphologyEx(255 - 圖像,cv2.MORPH_CLOSE,repair_kernel,迭代 = 1)cv2.imshow('thresh', thresh)cv2.imshow('detected_lines', detected_lines)cv2.imshow('圖像', 圖像)cv2.imshow('結果', 結果)cv2.waitKey()
Using the following code I can remove horizontal lines in images. See result below.
import cv2 from matplotlib import pyplot as plt img = cv2.imread('image.png',0) laplacian = cv2.Laplacian(img,cv2.CV_64F) sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5) plt.subplot(2,2,1),plt.imshow(img,cmap = 'gray') plt.title('Original'), plt.xticks([]), plt.yticks([]) plt.subplot(2,2,2),plt.imshow(laplacian,cmap = 'gray') plt.title('Laplacian'), plt.xticks([]), plt.yticks([]) plt.subplot(2,2,3),plt.imshow(sobelx,cmap = 'gray') plt.title('Sobel X'), plt.xticks([]), plt.yticks([]) plt.show()
The result is pretty good, not perfect but good. What I want to achieve is the one showed here. I am using this code.
Source image..
One of my questions is: how to save the
Sobel X
without that grey effect applied ? As original but processed..Also, is there a better way to do it ?
EDIT
Using the following code for the source image is good. Works pretty well.
import cv2 import numpy as np img = cv2.imread("image.png") img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) img = cv2.bitwise_not(img) th2 = cv2.adaptiveThreshold(img,255, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,15,-2) cv2.imshow("th2", th2) cv2.imwrite("th2.jpg", th2) cv2.waitKey(0) cv2.destroyAllWindows() horizontal = th2 vertical = th2 rows,cols = horizontal.shape #inverse the image, so that lines are black for masking horizontal_inv = cv2.bitwise_not(horizontal) #perform bitwise_and to mask the lines with provided mask masked_img = cv2.bitwise_and(img, img, mask=horizontal_inv) #reverse the image back to normal masked_img_inv = cv2.bitwise_not(masked_img) cv2.imshow("masked img", masked_img_inv) cv2.imwrite("result2.jpg", masked_img_inv) cv2.waitKey(0) cv2.destroyAllWindows() horizontalsize = int(cols / 30) horizontalStructure = cv2.getStructuringElement(cv2.MORPH_RECT, (horizontalsize,1)) horizontal = cv2.erode(horizontal, horizontalStructure, (-1, -1)) horizontal = cv2.dilate(horizontal, horizontalStructure, (-1, -1)) cv2.imshow("horizontal", horizontal) cv2.imwrite("horizontal.jpg", horizontal) cv2.waitKey(0) cv2.destroyAllWindows() verticalsize = int(rows / 30) verticalStructure = cv2.getStructuringElement(cv2.MORPH_RECT, (1, verticalsize)) vertical = cv2.erode(vertical, verticalStructure, (-1, -1)) vertical = cv2.dilate(vertical, verticalStructure, (-1, -1)) cv2.imshow("vertical", vertical) cv2.imwrite("vertical.jpg", vertical) cv2.waitKey(0) cv2.destroyAllWindows() vertical = cv2.bitwise_not(vertical) cv2.imshow("vertical_bitwise_not", vertical) cv2.imwrite("vertical_bitwise_not.jpg", vertical) cv2.waitKey(0) cv2.destroyAllWindows() #step1 edges = cv2.adaptiveThreshold(vertical,255, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,3,-2) cv2.imshow("edges", edges) cv2.imwrite("edges.jpg", edges) cv2.waitKey(0) cv2.destroyAllWindows() #step2 kernel = np.ones((2, 2), dtype = "uint8") dilated = cv2.dilate(edges, kernel) cv2.imshow("dilated", dilated) cv2.imwrite("dilated.jpg", dilated) cv2.waitKey(0) cv2.destroyAllWindows() # step3 smooth = vertical.copy() #step 4 smooth = cv2.blur(smooth, (4,4)) cv2.imshow("smooth", smooth) cv2.imwrite("smooth.jpg", smooth) cv2.waitKey(0) cv2.destroyAllWindows() #step 5 (rows, cols) = np.where(img == 0) vertical[rows, cols] = smooth[rows, cols] cv2.imshow("vertical_final", vertical) cv2.imwrite("vertical_final.jpg", vertical) cv2.waitKey(0) cv2.destroyAllWindows()
But if I have this image ?
I tried to execute the code above and the result is really poor...
Other images which I am working on are these...
解決方案Here's an approach
Convert image to grayscale
Otsu's threshold to get binary image
Create special horizontal kernel and morph open to detect horizontal lines
Find contours on mask and "fill in" the detected horizontal lines with white to effectively remove horizontal lines
Create vertical kernel and repair image with morph close
After converting to grayscale, we Otsu's threshold to obtain a binary image
image = cv2.imread('1.png') gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
Next we create a special horizontal kernel to detect horizontal lines. We draw these lines onto a mask and then find contours on the mask. To remove the lines, we fill in the contours with white
Detected lines
Mask
Filled in contours
# Remove horizontal horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (25,1)) detected_lines = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2) cnts = cv2.findContours(detected_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if len(cnts) == 2 else cnts[1] for c in cnts: cv2.drawContours(image, [c], -1, (255,255,255), 2)
The image currently has gaps. To fix this, we construct a vertical kernel to repair the image
# Repair image repair_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,6)) result = 255 - cv2.morphologyEx(255 - image, cv2.MORPH_CLOSE, repair_kernel, iterations=1)
Note depending on the image, the size of the kernel will change. For instance, to detect longer lines, we could use a
(50,1)
kernel instead. If we wanted thicker lines, we could increase the 2nd parameter to say(50,2)
.Here's the results with the other images
Detected lines
Original (left), removed (right)
Detected lines
Original (left), removed (right)
Full code
import cv2 image = cv2.imread('1.png') gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1] # Remove horizontal horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (25,1)) detected_lines = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2) cnts = cv2.findContours(detected_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if len(cnts) == 2 else cnts[1] for c in cnts: cv2.drawContours(image, [c], -1, (255,255,255), 2) # Repair image repair_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,6)) result = 255 - cv2.morphologyEx(255 - image, cv2.MORPH_CLOSE, repair_kernel, iterations=1) cv2.imshow('thresh', thresh) cv2.imshow('detected_lines', detected_lines) cv2.imshow('image', image) cv2.imshow('result', result) cv2.waitKey()
這篇關于刪除圖像中的水平線(OpenCV、Python、Matplotlib)的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!
【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!