2012-05-17 88 views
10

Tôi đã ghép hai ảnh lại với nhau bằng chức năng OpenCV và C++. Bây giờ tôi đang đối mặt với một vấn đề mà hình ảnh cuối cùng chứa một phần lớn màu đen.Làm thế nào để loại bỏ phần màu đen khỏi hình ảnh?

Hình ảnh cuối cùng phải là hình chữ nhật chứa phần có hiệu quả. Hình ảnh của tôi như sau:

enter image description here

Làm thế nào tôi có thể loại bỏ phần đen?

+0

Bạn có thể có thể sử dụng cvFindContours để có được mức độ của nội dung hình ảnh của bạn và sau đó cắt vào đó ... – LiMuBei

+2

khi thêm hình ảnh trong câu hỏi, xuất kết quả bằng cách sử dụng 'imwrite' và thêm nó. Nó là tốt hơn so với thêm ảnh chụp màn hình, bởi vì những người trả lời câu hỏi của bạn cần phải loại bỏ các vùng không mong muốn khỏi hình ảnh. –

+4

Không gian làm việc của bạn gọn gàng. – wengseng

Trả lời

16

mevatron Câu trả lời là một cách mà số lượng vùng màu đen được giảm thiểu trong khi giữ lại hình ảnh đầy đủ.

Một tùy chọn khác là xóa vùng màu đen hoàn chỉnh nơi bạn cũng mất một phần hình ảnh, nhưng kết quả sẽ là một hình ảnh hình chữ nhật trông gọn gàng. Dưới đây là mã Python.

Ở đây, bạn tìm thấy ba góc chính của hình ảnh như sau:

enter image description here

Tôi đã đánh dấu những giá trị đó. (1,x2), (x1,1), (x3,y3). Nó dựa trên giả định rằng hình ảnh của bạn bắt đầu từ (1,1).

Code:

bước đầu tiên là giống như mevatron 's. Làm mờ hình ảnh để loại bỏ nhiễu, đánh dấu hình ảnh, sau đó tìm đường nét.

import cv2 
import numpy as np 

img = cv2.imread('office.jpg') 
img = cv2.resize(img,(800,400)) 

gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 
gray = cv2.medianBlur(gray,3) 

ret,thresh = cv2.threshold(gray,1,255,0) 
contours,hierarchy = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) 

Bây giờ, tìm đường viền lớn nhất là hình ảnh của bạn. Nó là để tránh tiếng ồn trong trường hợp nếu có (Hầu hết có lẽ sẽ không có bất kỳ). Hoặc bạn có thể sử dụng phương thức mevatron.

max_area = -1 
best_cnt = None 

for cnt in contours: 

    area = cv2.contourArea(cnt) 
    if area > max_area: 
     max_area = area 
     best_cnt = cnt 

Bây giờ hãy ước tính đường bao để loại bỏ các điểm không cần thiết trong giá trị đường viền được tìm thấy, nhưng nó bảo toàn tất cả các giá trị góc.

approx = cv2.approxPolyDP(best_cnt,0.01*cv2.arcLength(best_cnt,True),True) 

Bây giờ chúng tôi tìm thấy các góc.

Đầu tiên, chúng tôi tìm thấy (x3, y3). Đó là điểm xa nhất. Vì vậy, x3*y3 sẽ rất lớn. Vì vậy, chúng tôi tìm thấy sản phẩm của tất cả các cặp điểm và chọn cặp với sản phẩm tối đa.

far = approx[np.product(approx,2).argmax()][0] 

Tiếp theo (1, x2). Đó là điểm mà phần tử đầu tiên là một phần tử, sau đó phần tử thứ hai là tối đa.

ymax = approx[approx[:,:,0]==1].max() 

Tiếp theo (x1,1). Đây là điểm mà phần tử thứ hai là 1, thì phần tử đầu tiên là tối đa.

xmax = approx[approx[:,:,1]==1].max() 

Bây giờ chúng ta tìm ra minimum values in (far.x,xmax) and (far.y, ymax)

x = min(far[0],xmax) 
y = min(far[1],ymax) 

Nếu bạn vẽ một hình chữ nhật với (1,1) và (x, y), bạn nhận được kết quả như sau:

enter image description here

Vì vậy, bạn cắt hình ảnh để sửa vùng hình chữ nhật.

img2 = img[:y,:x].copy() 

Dưới đây là kết quả:

enter image description here

See, the problem is that you lose some parts of the stitched image.

+1

: Kể từ khi tôi làm quen với C++ và cố gắng chuyển đổi mã (trong python) thành C++ nhưng không thể thành công nhiều. Nếu bạn có thể vui lòng chia sẻ cùng một mã trong ngôn ngữ C++, tôi sẽ rất biết ơn. –

+0

Tôi xin lỗi, tôi không giỏi trong C++. Nhưng nếu bạn cho tôi biết nếu bạn có bất kỳ nghi ngờ về bất kỳ bước trong phương pháp của tôi, tôi có thể giải thích theo cách đơn giản hơn nhiều. –

+0

: Tôi đã thực hiện tất cả các bước cho đến khi approxpolyDP, nhưng tôi không biết làm thế nào để tính toán sản phẩm của các điểm tọa độ trong C và tôi nghĩ rằng bạn cũng đã sử dụng mã giả.Có thể cho tôi biết làm thế nào tôi có thể tính toán sản phẩm của các điểm tọa độ trong C hoặc cung cấp cho tôi bất kỳ liên kết mà ai đó đã sử dụng loại phương pháp của bạn trong C.For tham khảo hình ảnh của tôi sau khi áp dụng phương pháp approxpoly() là [http://i.imgur.com/Qfoyt.jpg?1] .Hy vọng bạn cũng có cùng một hình ảnh đầu ra sau khi áp dụng approxpolyDp(). –

0

Bạn có thể sử dụng đường nét hoạt động (bóng bay/rắn) để chọn vùng màu đen chính xác. Một cuộc biểu tình có thể được tìm thấy here. Đường nét hoạt động có sẵn trong OpenCV, kiểm tra cvSnakeImage.

+0

Bạn có thể chỉ cho tôi cách thực hiện nó để loại bỏ phần màu đen? –

8

Bạn có thể thực hiện việc này với threshold, findContoursboundingRect.

Vì vậy, đây là một kịch bản nhanh làm điều này với giao diện python.

stitched = cv2.imread('stitched.jpg', 0) 
(_, mask) = cv2.threshold(stitched, 1.0, 255.0, cv2.THRESH_BINARY); 

# findContours destroys input 
temp = mask.copy() 
(contours, _) = cv2.findContours(temp, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 

# sort contours by largest first (if there are more than one) 
contours = sorted(contours, key=lambda contour:len(contour), reverse=True) 
roi = cv2.boundingRect(contours[0]) 

# use the roi to select into the original 'stitched' image 
stitched[roi[1]:roi[3], roi[0]:roi[2]] 

Kết thúc lên tìm kiếm như thế này: enter image description here

LƯU Ý: Sorting thể không cần thiết với hình ảnh thô, nhưng sử dụng các hình ảnh nén gây ra một số đồ tạo tác nén để hiển thị khi sử dụng một ngưỡng thấp, vì vậy đó là lý do tôi xử lý sau khi sắp xếp.

Hy vọng điều đó sẽ hữu ích!

+0

+1 ví dụ làm việc tuyệt vời. – karlphillip

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