2013-09-30 2 views
4

Как использовать стандартные фильтры обработки изображений (из OpenCV) для удаления длинных горизонтальных и вертикальных линий из изображения?Удаление длинных горизонтальных/вертикальных линий из изображения края с использованием OpenCV

Изображения B & W так что удаление означает просто покраску черного цвета.

Иллюстрация:

illustration of required filter

Я в настоящее время делает это в Python, итерацию над пиксельных строк и COLS и обнаружения диапазоны последовательных пикселей, удаляя те, которые больше, чем N пикселей. Однако он по-прежнему медленный по сравнению с библиотекой OpenCV, и если есть способ сделать то же самое с функциями OpenCV, это, вероятно, будет на порядок быстрее.

Я предполагаю, что это можно сделать путем свертки с использованием ядра, представляющего собой ряд пикселей (для горизонтальных линий), но мне сложно определить точную операцию, которая бы сделала трюк.

+2

Просто подумайте здесь. Почему бы вам не использовать Hough Line Detection для поиска строк и делать то, что вы хотите по выбранным линиям? –

+1

Yep собирался опубликовать то же самое на [docs] (http://docs.opencv.org/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.html) и [теория] (http: // en.wikipedia.org/wiki/Hough_transform#Theory) при необходимости. – YXD

+0

Кажется, что возвращаются сегменты длинной линии, разбитые на многие мелкие, что разрушает способность фильтровать недостаточно длинные ... любую идею, почему это произойдет? –

ответ

6

, если ваши линии действительно по горизонтали/вертикали, попробуйте этот

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)  

результат

enter image description here

+0

Может ли кто-нибудь объяснить python-ignorant, что linek = np.zeros ((11,11), dtype = np.uint8) linek [5, ...] = 1 делает? C++ preferred; ~) –

+3

'Mat linek = Mat :: zeros (Размер (11,11), CV_8UC1); linek.row (5) = 255;' –

1

Сколько времени "длинный". Длинные, как и в, линии, которые управляют длиной всего изображения, или длиннее, чем n пикселей?

Если последний, то вы можете просто использовать медианный или режимный фильтр n+1 X n+1 и установить коэффициенты угла в ноль, и вы получите желаемый эффект.

Если вы имеете в виду только строки, которые управляют шириной всего изображения, просто используйте функцию memcmp() против строки данных и сравните ее с предварительно выделенным массивом нулей, который имеет такую ​​же длину, как и ряд. Если они одинаковы, вы знаете, что у вас есть пустая строка, которая охватывает горизонтальную длину изображения, и эту строку можно удалить.

Это будет гораздо быстрее, чем поэлементного сравнения вы сейчас используете, и очень хорошо объяснено здесь:

Why is memcpy() and memmove() faster than pointer increments?

Если вы хотите, чтобы повторить ту же операцию для вертикальных линий, просто транспонировать изображение и повторите операцию.

Я знаю, что это более подход к уровню системной оптимизации, чем фильтр openCV, как вы просили, но он быстро и безопасно выполняет работу. Вы можете ускорить вычисление еще больше, если вам удастся заставить изображение, а ваш пустой массив - 32-битным, выровненным в памяти.

0

Чтобы удалить горизонтальные линии от изображения вы можете использовать алгоритм в обнаружении края для обнаружения краев и затем используйте преобразование Hough's в OpenCV для обнаружения линий и их цвет:

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) 
-1

Это для 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); 

      } 
    } 
+0

Первый, вы можете удалить вертикальные линии и горизонтальные линии в одно изображение одновременно. Во-вторых, вы можете удалить вертикальные линии и горизонтальные линии на одном изображении отдельно. То есть вы получите изображение без вертикальных линий или без горизонтальных линий. –

+0

@goto, если вы не проверяли мои коды, почему вы нажали неприязнь? –

-1

Другое.

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); 
    } 
} 
Смежные вопросы