将OpenCV图像转换为黑白图像
computer-vision
image-processing
opencv
python
6
0

如何将灰度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()
参考资料:
Stack Overflow
收藏
评论
共 7 个回答
高赞 时间 活跃

对于那些做视频的人,我根据@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()

结果是:

在此处输入图片说明

收藏
评论

使用新的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)

使用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位图像。如果您的图片是8bit,请使用以下算法:

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

如果具有8位图像,则无论阈值的大小如何。

收藏
评论

只需编写以下代码片段,即可将OpenCV图像转换为灰度图像

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%的阈值

在此处输入图片说明

为什么是33%?

这是因为33%的图像适用于大多数图像/数据集。

您也可以通过将median替换为mean来制定相同的方法。

方法2

另一种方法是在正数或负数上取均值的x个标准差( std );并设置一个阈值。因此可能是以下之一:

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

注:申请门槛之前,建议以增强灰度图像的对比度本地 (见CLAHE )。

收藏
评论

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

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

image_8U = np.uint8(abs_image_in32_64)
收藏
评论

指定CV_THRESH_OTSU导致阈值被忽略。从文档中

另外,特殊值THRESH_OTSU可以与以上值之一组合。在这种情况下,该函数使用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;
}
收藏
评论
新手导航
  • 社区规范
  • 提出问题
  • 进行投票
  • 个人资料
  • 优化问题
  • 回答问题

关于我们

常见问题

内容许可

联系我们

@2020 AskGo
京ICP备20001863号