如何使用标准图像处理过滤器(来自 OpenCV)从图像中删除长的水平和垂直线?
图像是黑白的,因此删除意味着简单地涂黑。
插图:
我目前正在使用 Python 进行此操作,遍历像素行和列并检测连续像素的范围,删除那些长于 N 像素的像素。但是,与 OpenCV 库相比,它确实很慢,如果有办法用 OpenCV 函数完成同样的任务,那可能会快几个数量级。
我想这可以通过使用一行像素(对于水平线)的内核进行卷积来完成,但是我很难确定可以解决问题的确切操作。
如何使用标准图像处理过滤器(来自 OpenCV)从图像中删除长的水平和垂直线?
图像是黑白的,因此删除意味着简单地涂黑。
插图:
我目前正在使用 Python 进行此操作,遍历像素行和列并检测连续像素的范围,删除那些长于 N 像素的像素。但是,与 OpenCV 库相比,它确实很慢,如果有办法用 OpenCV 函数完成同样的任务,那可能会快几个数量级。
我想这可以通过使用一行像素(对于水平线)的内核进行卷积来完成,但是我很难确定可以解决问题的确切操作。
如果你的线条是真正水平/垂直的,试试这个
import cv2
import numpy as np
img = cv2.imread('c:/data/test.png')
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
linek = np.zeros((11,11),dtype=np.uint8)
linek[5,...]=1
x=cv2.morphologyEx(gray, cv2.MORPH_OPEN, linek ,iterations=1)
gray-=x
cv2.imshow('gray',gray)
cv2.waitKey(0)
结果
您可以参考OpenCV Morphological Transformations文档了解更多详细信息。
“长”有多长。长,例如,贯穿整个图像长度的线条,还是比n
像素长?
如果是后者,那么您可以只使用n+1
Xn+1
中值或模式滤波器,并将角系数设置为零,您将获得所需的效果。
如果您仅指的是整个图像宽度的线条,只需memcmp()
对一行数据使用该函数,并将其与与行长度相同的预分配零数组进行比较。如果它们相同,则您知道您有一个跨越图像水平长度的空白行,并且可以删除该行。
这将比您当前使用的元素比较快得多,并且在这里得到了很好的解释:
为什么 memcpy() 和 memmove() 比指针增量快?
如果要对垂直线重复相同的操作,只需转置图像,然后重复操作。
我知道这更像是一种系统优化级别的方法,而不是您要求的 openCV 过滤器,但它可以快速安全地完成工作。如果您设法强制图像和空数组在内存中以 32 位对齐,则可以进一步加快计算速度。
要从图像中删除水平线,您可以使用边缘检测算法来检测边缘,然后使用 OpenCV 中的 Hough 变换来检测线并将它们着色为白色:
import cv2
import numpy as np
img = cv2.imread(img,0)
laplacian = cv2.Laplacian(img,cv2.CV_8UC1) # Laplacian Edge Detection
minLineLength = 900
maxLineGap = 100
lines = cv2.HoughLinesP(laplacian,1,np.pi/180,100,minLineLength,maxLineGap)
for line in lines:
for x1,y1,x2,y2 in line:
cv2.line(img,(x1,y1),(x2,y2),(255,255,255),1)
cv2.imwrite('Written_Back_Results.jpg',img)
这是针对 javacv 的。
包 com.test11;
import org.opencv.core.*;
import org.opencv.imgproc.Imgproc;
import org.opencv.imgcodecs.Imgcodecs;
public class GetVerticalOrHorizonalLines {
static{ System.loadLibrary(Core.NATIVE_LIBRARY_NAME); }
public static void main(String[] args) {
//Canny process before HoughLine Recognition
Mat source = Imgcodecs.imread("src//data//bill.jpg");
Mat gray = new Mat(source.rows(),source.cols(),CvType.CV_8UC1);
Imgproc.cvtColor(source, gray, Imgproc.COLOR_BGR2GRAY);
Mat binary = new Mat();
Imgproc.adaptiveThreshold(gray, binary, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 15, -2);
Imgcodecs.imwrite("src//data//binary.jpg", binary);
Mat horizontal = binary.clone();
int horizontalsize = horizontal.cols() / 30;
int verticalsize = horizontal.rows() / 30;
Mat horizontal_element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(horizontalsize,1));
//Mat element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3,3));
Imgcodecs.imwrite("src//data//horizontal_element.jpg", horizontal_element);
Mat Linek = Mat.zeros(source.size(), CvType.CV_8UC1);
//x = Imgproc.morphologyEx(gray, dst, op, kernel, anchor, iterations);
Imgproc.morphologyEx(gray, Linek,Imgproc.MORPH_BLACKHAT, horizontal_element);
Imgcodecs.imwrite("src//data//bill_RECT_Blackhat.jpg", Linek);
Mat vertical_element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(1,verticalsize));
Imgcodecs.imwrite("src//data//vertical_element.jpg", vertical_element);
Mat Linek2 = Mat.zeros(source.size(), CvType.CV_8UC1);
//x = Imgproc.morphologyEx(gray, dst, op, kernel, anchor, iterations);
Imgproc.morphologyEx(gray, Linek2,Imgproc.MORPH_CLOSE, vertical_element);
Imgcodecs.imwrite("src//data//bill_RECT_Blackhat2.jpg", Linek2);
}
}
另一个。
package com.test12;
import org.opencv.core.*;
import org.opencv.imgproc.Imgproc;
import org.opencv.imgcodecs.Imgcodecs;
public class ImageSubstrate {
static{ System.loadLibrary(Core.NATIVE_LIBRARY_NAME); }
public static void main(String[] args) {
Mat source = Imgcodecs.imread("src//data//bill.jpg");
Mat image_h = Mat.zeros(source.size(), CvType.CV_8UC1);
Mat image_v = Mat.zeros(source.size(), CvType.CV_8UC1);
Mat output = new Mat();
Core.bitwise_not(source, output);
Mat output_result = new Mat();
Mat kernel_h = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(20, 1));
Imgproc.morphologyEx(output, image_h, Imgproc.MORPH_OPEN, kernel_h);
Imgcodecs.imwrite("src//data//output.jpg", output);
Core.subtract(output, image_h, output_result);
Imgcodecs.imwrite("src//data//output_result.jpg", output_result);
Mat kernel_v = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(1, 20));
Imgproc.morphologyEx(output_result, image_v, Imgproc.MORPH_OPEN, kernel_v);
Mat output_result2 = new Mat();
Core.subtract(output_result, image_v, output_result2);
Imgcodecs.imwrite("src//data//output_result2.jpg", output_result2);
}
}