将OpenCV图像转换为黑白图像

python image-processing opencv computer-vision

99710 观看

7回复

22561 作者的声誉

如何将灰度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()
作者: Cerin 的来源 发布者: 2011 年 10 月 2 日

回应 (7)


8

7565 作者的声誉

指定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;
}
作者: SSteve 发布者: 02.10.2011 07:07

74

1211 作者的声誉

决定

使用新的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)
作者: tsh 发布者: 03.10.2011 04:17

1

34 作者的声誉

注意,如果你使用cv.CV_THRESH_BINARY意味着每个大于阈值的像素变为maxValue(在你的情况下为255),否则值为0.显然,如果你的阈值为0,一切都变为白色(maxValue = 255),如果值为255,一切都变为黑色(即0)。

如果您不想计算出阈值,可以使用Otsu的方法。但是该算法仅适用于OpenCV实现中的8bit图像。如果您的图像是8位,请使用以下算法:

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

如果您有8位图像,无论阈值如何。

作者: javier 发布者: 14.06.2013 08:08

4

91 作者的声誉

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

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

观察到image.jpg和代码必须保存在同一个文件夹中。

注意:

  • ('image.jpg') 给出RGB图像
  • ('image.jpg',0) 给出灰度图像。
作者: Ananth Reddy 发布者: 26.01.2017 06:01

3

7785 作者的声誉

方法1

在将灰度图像转换为二值图像时,我们通常cv2.threshold()手动使用和设置阈值。有时为了获得不错的结果,我们选择大津的二值化

我在阅读一些博客文章时遇到了一个小黑客。

  1. 将颜色(RGB)图像转换为灰度。
  2. 获得灰度图像的中值。
  3. 选择比中位数高出33%的阈值

在此输入图像描述

为什么33%?

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

您也可以通过更换工作了同样的方法medianmean

方法2

另一种方法是从正面或负面采取x一些标准偏差(std); 并设定一个门槛。所以它可能是以下之一:

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

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

作者: Jeru Luke 发布者: 24.02.2017 08:53

1

189 作者的声誉

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

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

image_8U = np.uint8(abs_image_in32_64)
作者: Santhosh 发布者: 24.08.2017 06:05

0

1357 作者的声誉

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

结果是:

在此输入图像描述

作者: Keno 发布者: 12.11.2018 07:45
32x32