Làm cách nào để làm sắc nét hình ảnh trong OpenCV?


122

Làm cách nào để làm sắc nét hình ảnh bằng OpenCV ?

Có nhiều cách làm mịn hoặc làm mờ nhưng không có cách nào mà tôi có thể thấy để làm sắc nét.

Câu trả lời:


160

Một quy trình chung được trình bày trong bài viết Wikipedia về che mặt nạ unsharp :

Bạn sử dụng bộ lọc làm mịn Gaussian và trừ phiên bản làm mịn khỏi ảnh gốc (theo cách có trọng số để các giá trị của một vùng không đổi không đổi).

Để có được một phiên bản mài nhọn của framethành image: (cả hai cv::Mat)

cv::GaussianBlur(frame, image, cv::Size(0, 0), 3);
cv::addWeighted(frame, 1.5, image, -0.5, 0, image);

Các thông số ở đó bạn cần điều chỉnh cho mình.

Ngoài ra còn có mài mòn Laplacian, bạn sẽ tìm thấy thứ gì đó trên đó khi bạn google.


1
Có cách nào để sao chép kết quả Unsharp Mask của Photoshop không?
Royi

@Drazick Bạn đang hỏi vì nó không thể sao chép? liên kết đến wikipedia đã được đưa ra ở trên. cụ thể là digital_unsharp_masking
Tilaprimera

@tilaprimera, tôi đang hỏi vì USM của Photoshop khác với USM "Cổ điển".
Royi

50

Bạn có thể thử một hạt nhân đơn giản và hàm filter2D , ví dụ như trong Python:

kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])
im = cv2.filter2D(im, -1, kernel)

Wikipedia có tổng quan tốt về hạt nhân với một số ví dụ khác tại đây - https://en.wikipedia.org/wiki/Kernel_(image_processing)

Trong xử lý ảnh, hạt nhân, ma trận tích chập hoặc mặt nạ là một ma trận nhỏ. Nó được sử dụng để làm mờ, làm sắc nét, làm nổi, phát hiện cạnh, v.v. Điều này được thực hiện bằng cách thực hiện phép tích chập giữa hạt nhân và hình ảnh.


14

Bạn có thể tìm thấy mã mẫu về việc làm sắc nét hình ảnh bằng thuật toán "unsharp mask" tại Tài liệu OpenCV .

Thay đổi giá trị của sigma, threshold, amountsẽ cho kết quả khác nhau.

// sharpen image using "unsharp mask" algorithm
Mat blurred; double sigma = 1, threshold = 5, amount = 1;
GaussianBlur(img, blurred, Size(), sigma, sigma);
Mat lowContrastMask = abs(img - blurred) < threshold;
Mat sharpened = img*(1+amount) + blurred*(-amount);
img.copyTo(sharpened, lowContrastMask);

Điều này là đẹp!
roosevelt

12

Bạn có thể làm sắc nét hình ảnh bằng cách sử dụng mặt nạ không làm mờ . Bạn có thể tìm thêm thông tin về mặt nạ unsharp tại đây . Và đây là một triển khai Python bằng OpenCV:

import cv2 as cv
import numpy as np

def unsharp_mask(image, kernel_size=(5, 5), sigma=1.0, amount=1.0, threshold=0):
    """Return a sharpened version of the image, using an unsharp mask."""
    blurred = cv.GaussianBlur(image, kernel_size, sigma)
    sharpened = float(amount + 1) * image - float(amount) * blurred
    sharpened = np.maximum(sharpened, np.zeros(sharpened.shape))
    sharpened = np.minimum(sharpened, 255 * np.ones(sharpened.shape))
    sharpened = sharpened.round().astype(np.uint8)
    if threshold > 0:
        low_contrast_mask = np.absolute(image - blurred) < threshold
        np.copyto(sharpened, image, where=low_contrast_mask)
    return sharpened

def example():
    image = cv.imread('my-image.jpg')
    sharpened_image = unsharp_mask(image)
    cv.imwrite('my-sharpened-image.jpg', sharpened_image)

đây có vẻ là một phiên bản khá tiện dụng. bạn có thể vui lòng thêm một chút thông tin về các thông số. kích thước hạt nhân và sigma có thể được tra cứu trong opencv, nhưng còn lượng và ngưỡng thì sao? Cảm ơn!
choise

2
@choise amountchỉ đơn giản là số lượng làm sắc nét. Ví dụ: amount2.0 cho hình ảnh sắc nét hơn so với giá trị mặc định là 1.0. thresholdlà ngưỡng cho mặt nạ có độ tương phản thấp. Nói cách khác, các pixel mà sự khác biệt giữa hình ảnh đầu vào và hình ảnh bị mờ nhỏ hơn thresholdsẽ không thay đổi.
Soroush

10

Bất kỳ Hình ảnh nào là tập hợp các tín hiệu có tần số khác nhau. Các tần số cao hơn kiểm soát các cạnh và các tần số thấp hơn kiểm soát nội dung hình ảnh. Các cạnh được hình thành khi có sự chuyển đổi rõ nét từ giá trị pixel này sang giá trị pixel khác như 0 và 255 trong ô liền kề. Rõ ràng là có một sự thay đổi mạnh mẽ và do đó cạnh và tần số cao. Để làm sắc nét hình ảnh, những chuyển đổi này có thể được tăng cường hơn nữa.

Một cách là kết hợp một nhân bộ lọc tự tạo với hình ảnh.

    import cv2
    import numpy as np

    image = cv2.imread('images/input.jpg')
    kernel = np.array([[-1,-1,-1], 
                       [-1, 9,-1],
                       [-1,-1,-1]])
    sharpened = cv2.filter2D(image, -1, kernel) # applying the sharpening kernel to the input image & displaying it.
    cv2.imshow('Image Sharpening', sharpened)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

Có một phương pháp khác để trừ phiên bản ảnh bị mờ khỏi phiên bản sáng của nó. Điều này giúp làm sắc nét hình ảnh. Nhưng nên làm một cách thận trọng vì chúng tôi chỉ đang tăng các giá trị pixel. Hãy tưởng tượng giá trị pixel thang độ xám 190, giá trị này nếu nhân với trọng số của 2 sẽ thành nếu 380, nhưng bị cắt xuống còn 255 do phạm vi pixel tối đa cho phép. Đây là sự mất mát thông tin và dẫn đến hình ảnh bị rửa trôi.

    addWeighted(frame, 1.5, image, -0.5, 0, image);

5

Để rõ ràng hơn về chủ đề này, một số điểm thực sự nên được thực hiện:

  1. Làm sắc nét hình ảnh là một vấn đề nan giải. Nói cách khác, làm mờ là một hoạt động mất mát và nói chung là không thể quay lại từ đó.

  2. Để làm sắc nét các hình ảnh đơn lẻ, bằng cách nào đó bạn cần thêm các ràng buộc (giả định) về loại hình ảnh bạn muốn và cách nó bị mờ. Đây là khu vực thống kê hình ảnh tự nhiên. Các phương pháp tiếp cận để làm sắc nét giữ các thống kê này một cách rõ ràng hoặc ẩn chứa trong các thuật toán của chúng (học sâu là những thống kê được mã hóa ngầm nhất). Cách tiếp cận phổ biến của việc tăng trọng số một số cấp độ của sự phân hủy kim tự tháp CHÓ hoặc Laplacian , là khái quát của câu trả lời Brian Burns, giả định rằng sự làm mờ Gaussian đã làm hỏng hình ảnh và cách thực hiện trọng số được kết nối với các giả định về những gì trong hình ảnh để bắt đầu.

  3. Các nguồn thông tin khác có thể làm cho vấn đề trở nên rõ ràng hơn. Các nguồn thông tin phổ biến như vậy là video về một đối tượng chuyển động hoặc cài đặt nhiều chế độ xem. Độ sắc nét trong cài đặt đó thường được gọi là siêu phân giải (một cái tên rất tệ đối với nó, nhưng nó đã bị mắc kẹt trong giới học thuật). Đã có những phương pháp siêu phân giải trong OpenCV từ rất lâu rồi .... mặc dù chúng thường không hoạt động tốt đối với các vấn đề thực tế lần cuối tôi đã kiểm tra chúng. Tôi hy vọng học sâu cũng sẽ tạo ra một số kết quả tuyệt vời ở đây. Có thể ai đó sẽ đăng nhận xét về những gì đáng giá ngoài kia.


3

Để làm sắc nét hình ảnh, chúng ta có thể sử dụng bộ lọc (như trong nhiều câu trả lời trước đây)

kernel = np.array([[-1, -1, -1],[-1, 8, -1],[-1, -1, 0]], np.float32) 

kernel /= denominator * kernel

Nó sẽ nhiều nhất khi mẫu số là 1 và sẽ giảm khi tăng (2.3 ..)

Một trong những được sử dụng nhiều nhất là khi mẫu số là 3.

Dưới đây là cách thực hiện.

kernel = np.array([[-1, -1, -1],[-1, 8, -1],[-1, -1, 0]], np.float32) 

kernel = 1/3 * kernel

dst = cv2.filter2D(image, -1, kernel)

Gần "It will the most" dường như thiếu một cái gì đó .
Peter Mortensen

Vâng, Peter, cảm ơn bạn!
kaustubhd9

-4

Hãy thử với cái này:

cv::bilateralFilter(img, 9, 75, 75);

Bạn có thể tìm thêm thông tin ở đây .


9
Câu hỏi là về làm sắc nét hình ảnh, không giữ nguyên cạnh làm mịn.
Michael Burdinov
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.