Преобразование изображения 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()
Ответы
Ответ 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-битное изображение.