Подтвердить что ты не робот

Преобразование изображения 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()
4b9b3361

Ответ 1

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

1. Прочтите изображение в градациях серого

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

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

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

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

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

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

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

Ответ 2

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

Кроме того, специальное значение THRESH_OTSU может быть объединено с одним из приведенных выше значений. В этом случае функция определяет оптимальное пороговое значение с использованием алгоритма Otsus и использует его вместо указанного порога. Функция возвращает вычисленное пороговое значение. В настоящее время метод Otsus реализован только для 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;
}

Ответ 3

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

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

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

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

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

Ответ 4

Подход 1

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

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

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

введите описание изображения здесь

Почему 33%?

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

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

Подход 2

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

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

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

Ответ 5

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

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

image_8U = np.uint8(abs_image_in32_64)

Ответ 6

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

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

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

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