将OpenCV图像转换为黑白图像

85 投票
7 回答
257958 浏览
提问于 2025-04-17 03:31

我想知道怎么把一个灰度的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 个回答

10

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

结果如下:

在这里输入图片描述

10

使用 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;
}
160

下面是一个逐步的解答,类似于你提到的内容,使用新的cv2 Python库:

1. 读取一张灰度图像

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

2. 将灰度图像转换为二进制图像

这个步骤会自动根据图像使用Otsu方法来确定阈值。如果你已经知道阈值,也可以使用:

(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)

撰写回答