it-roy-ru.com

Преобразование изображения OpenCV в черно-белое

Как преобразовать изображение OpenCV в градациях серого в черно-белое? Я вижу похожий вопрос уже задавался, но я использую OpenCV 2.3, и предложенное решение больше не работает.

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

Следующий Python почти полностью меня понял, но пороговое значение, отправленное в Threshold (), похоже, не имеет никакого эффекта. Если я установлю его на 0 или 16, или на 128, или на 255, результат будет таким же: все пиксели со значением> 128 станут белыми, а все остальное станет черным.

Что я делаю неправильно?

import cv, cv2
fn = 'myfile.jpg'
im_gray = cv2.imread(fn, cv.CV_LOAD_IMAGE_GRAYSCALE)
im_gray_mat = cv.fromarray(im_gray)
im_bw = cv.CreateImage(cv.GetSize(im_gray_mat), cv.IPL_DEPTH_8U, 1);
im_bw_mat = cv.GetMat(im_bw)
threshold = 0 # 128#255# HAS NO EFFECT!?!?
cv.Threshold(im_gray_mat, im_bw_mat, threshold, 255, cv.CV_THRESH_BINARY | cv.CV_THRESH_OTSU);
cv2.imshow('', np.asarray(im_bw_mat))
cv2.waitKey()
37
Cerin

Пошаговый ответ, аналогичный тому, на который вы ссылаетесь, с использованием новых привязок cv2 Python:

1. Чтение изображения в оттенках серого

import cv2
im_gray = cv2.imread('grayscale_image.png', cv2.IMREAD_GRAYSCALE)

2. Преобразовать изображение в градациях серого в двоичный файл

(thresh, im_bw) = cv2.threshold(im_gray, 128, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)

который определяет порог автоматически по изображению, используя метод Оцу, или, если вы уже знаете порог, вы можете использовать:

thresh = 127
im_bw = cv2.threshold(im_gray, thresh, 255, cv2.THRESH_BINARY)[1]

3. Сохранить на диск

cv2.imwrite('bw_image.png', im_bw)
79
tsh

Указание CV_THRESH_OTSU приводит к игнорированию порогового значения. Из документации

Также специальное значение THRESH_OTSU может быть объединено с одним из вышеуказанных значений. В этом случае функция определяет оптимальное пороговое значение с помощью алгоритма Оцу и использует его вместо указанного порога. Функция возвращает вычисленное пороговое значение. В настоящее время метод Оцу реализован только для 8-битных изображений.

Этот код читает кадры с камеры и выполняет двоичное пороговое значение со значением 20.

#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"

using namespace cv;

int main(int argc, const char * argv[]) {

    VideoCapture cap; 
    if(argc > 1) 
        cap.open(string(argv[1])); 
    else 
        cap.open(0); 
    Mat frame; 
    namedWindow("video", 1); 
    for(;;) {
        cap >> frame; 
        if(!frame.data) 
            break; 
        cvtColor(frame, frame, CV_BGR2GRAY);
        threshold(frame, frame, 20, 255, THRESH_BINARY);
        imshow("video", frame); 
        if(waitKey(30) >= 0) 
            break;
    }

    return 0;
}
8
SSteve

Просто вы можете написать следующий фрагмент кода для преобразования изображения OpenCV в изображение в оттенках серого

import cv2
image = cv2.imread('image.jpg',0)
cv2.imshow('grey scale image',image)

Обратите внимание, что image.jpg и код должны быть сохранены в одной папке. 

Обратите внимание, что:

  • ('image.jpg') дает изображение RGB
  • ('image.jpg',0) дает изображение серой шкалы.
5
Ananth Reddy

Подход 1

При преобразовании изображения в оттенках серого в двоичное изображение мы обычно используем cv2.threshold() и устанавливаем пороговое значение вручную. Иногда, чтобы получить достойный результат, мы выбираем бинаризация Оцу.

У меня есть небольшой взлом, с которым я столкнулся, читая некоторые сообщения в блоге.

  1. Преобразуйте ваше цветное (RGB) изображение в оттенки серого.
  2. Получите медиану серого изображения.
  3. Выберите пороговое значение на 33% выше среднего 

 enter image description here

Почему 33%?

Это потому, что 33% работает для большинства изображений/набора данных.

Вы также можете выработать тот же подход, заменив median на mean.

Подход 2

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

  • th1 = mean - (x * std)
  • th2 = mean + (x * std)

Примечание: Перед применением порогового значения желательно повысить контраст изображения серой шкалы локально (см. CLAHE ).

4
Jeru Luke

Обратите внимание, если вы используете cv.CV_THRESH_BINARY, значит каждый пиксель, превышающий пороговое значение, становится maxValue (в вашем случае 255), в противном случае значение равно 0. Очевидно, если ваш порог равен 0, все становится белым (maxValue = 255), а если значение равно 255 становится черным (то есть 0).

Если вы не хотите устанавливать порог, вы можете использовать метод Оцу. Но этот алгоритм работает только с 8-битными изображениями в реализации OpenCV. Если ваше изображение 8-битное, используйте алгоритм следующим образом:

cv.Threshold(im_gray_mat, im_bw_mat, threshold, 255, cv.CV_THRESH_BINARY | cv.CV_THRESH_OTSU);

Независимо от значения порога, если у вас есть 8-битное изображение.

1
javier

Вот двухстрочный код, который я нашел в Интернете и который может быть полезен для начинающих.

# Absolute value of the 32/64
abs_image_in32_64 = np.absolute(image_in32_64)

image_8U = np.uint8(abs_image_in32_64)
1
Santhosh

Для тех, кто делает видео, я применил следующее на основе @tsh:

import cv2 as cv
import numpy as np

def nothing(x):pass

cap = cv.VideoCapture(0)
cv.namedWindow('videoUI', cv.WINDOW_NORMAL)
cv.createTrackbar('T','videoUI',0,255,nothing)

while(True):
    ret, frame = cap.read()
    vid_gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
    thresh = cv.getTrackbarPos('T','videoUI');
    vid_bw = cv.threshold(vid_gray, thresh, 255, cv.THRESH_BINARY)[1]

    cv.imshow('videoUI',cv.flip(vid_bw,1))

    if cv.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv.destroyAllWindows()

Результаты в:

 enter image description here

0
Keno