OpenCV 图像的黑白转换

如何将灰度 OpenCV 图像转换为黑白图像?我看到一个 similar question已经被要求,但我正在使用 OpenCV 2.3,并提出的解决方案似乎不再工作。

I'm trying to convert a greyscale image to black and white, so that anything not absolutely black is white, and use this as a mask for 冲浪检测(), in order to ignore keypoints found on the edge of the black mask area.

下面的 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()
220409 次浏览

指定 CV_THRESH_OTSU将导致忽略阈值:

另外,特殊值 THRESH _ OTSU 可以与上述值之一组合。在这种情况下,函数使用 Otsu 的算法确定最佳阈值,并使用它来代替指定的阈值。该函数返回计算出的阈值。目前,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;
}

Step-by-step answer similar to the one you refer to, using the new cv2 Python bindings:

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)

它使用 Otsu 的方法自动从图像中确定阈值,或者如果你已经知道阈值,你可以使用:

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

3. 保存到磁盘

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

请注意,如果使用 cv.CV_THRESH_BINARY表示每个大于阈值的像素都成为 maxValue (在您的示例中为255) ,否则值为0。显然,如果阈值为0,则所有内容都变成白色(maxValue = 255) ,如果值为255,则所有内容都变成黑色(即0)。

如果你不想确定一个阈值,你可以使用 Otsu 的方法。但在 OpenCV 的实现中,该算法只能处理8位图像。如果你的图像是8位的,使用这样的算法:

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

不管阈值的大小,如果你有一个8位图像。

Simply you can write the following code snippet to convert an OpenCV image into a grey scale image

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

请注意,image. jpg 和代码必须保存在同一个文件夹中。

请注意:

  • ('image.jpg')给出一个 RGB 图像
  • ('image.jpg',0)提供灰度图像。

进场1

在将灰度图像转换为二值图像时,我们通常使用 cv2.threshold()并手动设置阈值。有时为了得到一个体面的结果,我们选择 Otsu 的二元化

我在阅读一些博客文章时偶然发现了一个小黑客。

  1. 将彩色(RGB)图像转换为灰度。
  2. 获取灰度图像的中值。
  3. 选择一个比中值高33% 的阈值

enter image description here

为什么是33% ?

This is because 33% works for most of the images/data-set.

您还可以通过用 mean替换 median来实现相同的方法。

进场二

另一种方法是从平均值的 x个标准偏差(std) ,无论是在正面还是负面; 并设置一个阈值。所以可能是下列情况之一:

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

注意: 在应用阈值之前,建议增强灰度图像 本地的对比度(见 (咔嚓声))。

这是我在网上找到的两行代码,可能对初学者有帮助

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


image_8U = np.uint8(abs_image_in32_64)

对于那些制作视频的人,我基于@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