Преобразование изображения OpenCV в черно-белое - PullRequest
43 голосов
/ 02 октября 2011

Как конвертировать черно-белое изображение 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()

Ответы [ 7 ]

83 голосов
/ 03 октября 2011

Пошаговый ответ, аналогичный тому, на который вы ссылаетесь, с использованием новых привязок 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)
8 голосов
/ 02 октября 2011

Указание 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;
}
5 голосов
/ 26 января 2017

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

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

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

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

  • ('image.jpg') дает RGB-изображение
  • ('image.jpg',0) дает изображение серой шкалы.
4 голосов
/ 24 февраля 2017

Подход 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 ).

1 голос
/ 24 августа 2017

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

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

image_8U = np.uint8(abs_image_in32_64)
1 голос
/ 15 июня 2013

Обратите внимание, если вы используете 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-битное изображение.

0 голосов
/ 12 ноября 2018

Для тех, кто делает видео, я применил следующее на основе @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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...