2015-10-05 18 views
5

Tôi có một hình ảnh mẫu như thế nàyLàm thế nào để trích xuất vùng màu trắng trong một hình ảnh

enter image description here

Tôi đang tìm kiếm một cách để màu đen ra tiếng ồn từ các hình ảnh như vậy mà tôi kết thúc với một hình ảnh mà chỉ có văn bản màu đen trên nền trắng để tôi có thể gửi nó để tesseract.

Tôi đã thử kỹ xảo với

kernel = np.ones((4,4),np.uint8) 
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) 
cv2.imshow("opening", opening) 

nhưng nó dường như không làm việc.

Tôi cũng đã cố gắng để tìm thấy đường nét

img = cv2.cvtColor(rotated, cv2.COLOR_BGR2GRAY) 
(cnts, _) = cv2.findContours(img, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) 
cnts = sorted(cnts, key = cv2.contourArea, reverse = True)[:1] 
for c in cnts: 
    x,y,w,h = cv2.boundingRect(c) 
    roi=rotated[y:y+h,x:x+w].copy() 
    cv2.imwrite("roi.png", roi) 

Với đoạn mã trên, tôi nhận được những đường nét sau:

enter image description here

dẫn đến hình ảnh này khi cắt:

enter image description here

vẫn chưa đủ tốt. Tôi muốn văn bản màu đen trên nền trắng, vì vậy mà tôi có thể gửi nó để tesseract OCR và có tỷ lệ thành công tốt.

Có bất kỳ điều gì khác mà tôi có thể thử không?

Cập nhật

Dưới đây là một hình ảnh tương tự bổ sung. Cái này là một chút dễ dàng hơn bởi vì nó có một hình chữ nhật trơn tru trong đó

enter image description here

+1

với cử tri người đã nói câu hỏi là quá rộng. Vui lòng cho tôi biết cách thu hẹp thêm. Tôi không nghĩ rằng câu hỏi là rộng .. – Anthony

+0

Bạn cần phải làm một số thresholding thích ứng, và mở và đóng hoạt động. http://docs.opencv.org/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.html Bạn cũng có thể làm xói mòn hoặc giãn nở tùy chỉnh (điều cơ bản là những hoạt động mở và đóng hoạt động). –

+0

Đây có phải là hình ảnh đầu vào không? Hoặc kết quả từ một số loại thresholding? – ZdaR

Trả lời

3

Tác phẩm sau đây cho ví dụ cụ thể của bạn, mặc dù nó có thể cần tinh chỉnh cho phạm vi hình ảnh rộng hơn.

import numpy as np 
import cv2 

image_src = cv2.imread("input.png") 
gray = cv2.cvtColor(image_src, cv2.COLOR_BGR2GRAY) 
ret, gray = cv2.threshold(gray, 250,255,0) 

image, contours, hierarchy = cv2.findContours(gray, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) 
largest_area = sorted(contours, key=cv2.contourArea)[-1] 
mask = np.zeros(image_src.shape, np.uint8) 
cv2.drawContours(mask, [largest_area], 0, (255,255,255,255), -1) 
dst = cv2.bitwise_and(image_src, mask) 
mask = 255 - mask 
roi = cv2.add(dst, mask) 

roi_gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY) 
ret, gray = cv2.threshold(roi_gray, 250,255,0) 
image, contours, hierarchy = cv2.findContours(gray, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) 

max_x = 0 
max_y = 0 
min_x = image_src.shape[1] 
min_y = image_src.shape[0] 

for c in contours: 
    if 150 < cv2.contourArea(c) < 100000: 
     x, y, w, h = cv2.boundingRect(c) 
     min_x = min(x, min_x) 
     min_y = min(y, min_y) 
     max_x = max(x+w, max_x) 
     max_y = max(y+h, max_y) 

roi = roi[min_y:max_y, min_x:max_x] 
cv2.imwrite("roi.png", roi) 

Đem lại cho bạn các loại vật liệu làm hình ảnh đầu ra:

enter image description here

Và ...

enter image description here

Mã này hoạt động bằng cách đầu tiên định vị khu vực đường viền lớn nhất. Từ đây một mặt nạ được tạo ra được sử dụng để đầu tiên chỉ chọn khu vực bên trong, tức là văn bản. Nghịch đảo của mặt nạ sau đó được thêm vào hình ảnh để chuyển đổi khu vực bên ngoài mặt nạ thành màu trắng.

Đường viền cuối cùng được tìm thấy lần nữa cho hình ảnh mới này. Bất kỳ khu vực đường viền nào bên ngoài phạm vi kích thước phù hợp đều bị loại bỏ (điều này được sử dụng để bỏ qua bất kỳ khu vực tiếng ồn nhỏ nào), và một đường cong giới hạn được tìm thấy cho mỗi vùng. Với mỗi hình chữ nhật này, đường biên giới hạn outer được tính toán cho tất cả các đường bao còn lại và một cây trồng được thực hiện bằng cách sử dụng các giá trị này để cung cấp cho hình ảnh cuối cùng.

Cập nhật - Để có được phần còn lại của hình ảnh, ví dụ: với diện tích trên bị loại bỏ, sau đây có thể được sử dụng:

image_src = cv2.imread("input.png") 
gray = cv2.cvtColor(image_src, cv2.COLOR_BGR2GRAY) 
ret, gray = cv2.threshold(gray, 10, 255,0) 
image, contours, hierarchy = cv2.findContours(gray, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) 
largest_area = sorted(contours, key=cv2.contourArea)[-1] 
mask = np.zeros(image_src.shape, np.uint8) 
cv2.drawContours(mask, [largest_area], 0, (255,255,255,255), -1) 
image_remainder = cv2.bitwise_and(image_src, 255 - mask) 

cv2.imwrite("remainder.png", image_remainder) 
+0

Nếu có thể, bạn có thể giải thích cách tiếp cận của bạn. Cảm ơn câu trả lời! – Anthony

+0

Không sao, tôi đã cập nhật phần giải thích. –

+0

cảm ơn. hmm Tôi gặp lỗi trên dòng 8 'hình ảnh, đường nét, phân cấp = cv2.findContours (màu xám, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) Giá trị lỗi: cần nhiều hơn 2 giá trị để giải nén ' – Anthony

0

ý tưởng cơ bản của câu trả lời này là sử dụng đường viền bao quanh văn bản.

1) Erodengang với một hạt nhân rất lớn, nói kích thước 100 px hoặc 8 lần kích thước của nhân vật dự kiến ​​duy nhất, một cái gì đó như thế. Nó nên được thực hiện hàng khôn ngoan. Điều phối cực đoan sẽ cho biết vị trí của các ranh giới xung quanh văn bản.

2) Quy trình theo chiều dọc cùng một cách để có được vị trí x của ranh giới xung quanh văn bản. Sau đó, sử dụng các vị trí này để cắt hình ảnh bạn muốn.

- Một lợi ích của phương pháp này là bạn sẽ nhận được mọi câu/từ được phân đoạn riêng mà, tôi đoán, là tốt cho một OCR.

Chúc mừng Mã hóa :)

Sửa Mark Setchell

Đây là một bản demo của 1)

enter image description here

Đây là một bản demo của 2)

enter image description here

+1

Tôi hy vọng bạn không nhớ tôi bổ sung một hình ảnh động - cảm thấy tự do để xóa nó nếu bạn làm. –

+0

Xin chào @MarkSetchell, wow những điều này thực sự tuyệt vời :) Cảm ơn –

+0

Tôi sẽ thử phương pháp này vì nó có thể áp dụng nhiều hơn cho các hình ảnh tương tự khác. Tôi sẽ cập nhật tiến trình của mình ở đây. Tôi hy vọng opencv có một cách để làm ngang và dọc eroding – Anthony

0

tôi có được điều này: Mã Result

Nguồn:

if __name__ == '__main__': 
    SrcImg = cv2.imread('./Yahi9.png', cv2.CV_LOAD_IMAGE_GRAYSCALE) 
    _, BinImg = cv2.threshold(SrcImg, 80, 255, cv2.THRESH_OTSU) 

    Contours, Hierarchy = cv2.findContours(image=copy.deepcopy(SrcImg), 
             mode=cv2.cv.CV_RETR_EXTERNAL, 
             method=cv2.cv.CV_CHAIN_APPROX_NONE) 
    MaxContour, _ = getMaxContour(Contours) 
    Canvas = np.ones(SrcImg.shape, np.uint8) 
    cv2.drawContours(image=Canvas, contours=[MaxContour], contourIdx=0, color=(255), thickness=-1) 
    mask = (Canvas != 255) 
    RoiImg = copy.deepcopy(BinImg) 
    RoiImg[mask] = 255 
    RoiImg = cv2.morphologyEx(src=RoiImg, op=cv2.MORPH_CLOSE, kernel=np.ones((3,3)), iterations=4) 
    cv2.imshow('RoiImg', RoiImg) 
    cv2.waitKey(0) 

Chức năng:

def getMaxContour(contours): 
    MaxArea = 0 
    Location = 0 
    for idx in range(0, len(contours)): 
     Area = cv2.contourArea(contours[idx]) 
     if Area > MaxArea: 
      MaxArea = Area 
      Location = idx 
    MaxContour = np.array(contours[Location]) 
    return MaxContour, MaxArea 

Ehh, nó là mã python. Nó chỉ hoạt động khi vùng trắng là đường bao tối đa.

+0

Nếu có thể, bạn có thể vui lòng giải thích cách tiếp cận của bạn. Cảm ơn câu trả lời! – Anthony

+0

Tôi xin lỗi, tôi đã rất mệt mỏi khi ngủ thiếp đi ngay khi tôi về nhà. –

+0

Martin Evans sử dụng cùng một cách để trích xuất, nó khá tốt. –

Các vấn đề liên quan