在OpenCV中将RGB转换为黑白

67

我想知道如何将RGB图像转换为黑白(二进制)图像。

转换后,如何将修改后的图像保存到磁盘上?

5个回答

144

据我所知,您需要将其转换为灰度图像,然后再将其阈值化为二进制。

1.读取图像作为灰度图像 如果您从磁盘读取RGB图像,则可以直接将其作为灰度图像读取,如下所示:

// C
IplImage* im_gray = cvLoadImage("image.jpg",CV_LOAD_IMAGE_GRAYSCALE);

// C++ (OpenCV 2.0)
Mat im_gray = imread("image.jpg",CV_LOAD_IMAGE_GRAYSCALE);

2. 将RGB图像im_rgb转换为灰度图像:否则,您将不得不将先前获得的RGB图像转换为灰度图像

// C
IplImage *im_rgb  = cvLoadImage("image.jpg");
IplImage *im_gray = cvCreateImage(cvGetSize(im_rgb),IPL_DEPTH_8U,1);
cvCvtColor(im_rgb,im_gray,CV_RGB2GRAY);

// C++
Mat im_rgb  = imread("image.jpg");
Mat im_gray;
cvtColor(im_rgb,im_gray,CV_RGB2GRAY);

3. 转换为二进制 您可以使用自适应阈值处理固定阈值处理将灰度图像转换为二进制图像。

例如,在C语言中,您可以执行以下操作(您也可以使用Mat和相应的函数在C++中执行相同操作):

// C
IplImage* im_bw = cvCreateImage(cvGetSize(im_gray),IPL_DEPTH_8U,1);
cvThreshold(im_gray, im_bw, 128, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);

// C++
Mat img_bw = im_gray > 128;

在上面的例子中,128是阈值。

4. 保存到磁盘

// C
cvSaveImage("image_bw.jpg",img_bw);

// C++
imwrite("image_bw.jpg", img_bw);

根据应用程序,您可能希望执行抖动而不是简单阈值。 - Mark Ransom
在CvtColor函数中,我们需要使用CV_BGR2GRAY还是CV_RGB2GRAY?我已经阅读过OpenCV基于BGR格式并且我们需要使用它,但在灰度或二进制图像中,当使用其中任何一个时,我没有看到任何区别。 - evk1206

3
"

这对我来说似乎起作用了!

"
Mat a_image = imread(argv[1]);

cvtColor(a_image, a_image, CV_BGR2GRAY);
GaussianBlur(a_image, a_image, Size(7,7), 1.5, 1.5);
threshold(a_image, a_image, 100, 255, CV_THRESH_BINARY);

1

简单的二值化阈值方法就足够了。

#include

#include <string>
#include "opencv/highgui.h"
#include "opencv2/imgproc/imgproc.hpp"

using namespace std;
using namespace cv;

int main()
{
    Mat img = imread("./img.jpg",0);//loading gray scale image
    threshold(img, img, 128, 255, CV_THRESH_BINARY);//threshold binary, you can change threshold 128 to your convenient threshold
    imwrite("./black-white.jpg",img);
    return 0;
}

你可以使用 GaussianBlur 来获取平滑的黑白图像。

1
一个简单的将图像“二值化”的方法是与阈值进行比较: 例如,您可以使用C++中的OpenCV将矩阵中的所有元素与一个值进行比较。
cv::Mat img = cv::imread("image.jpg", CV_LOAD_IMAGE_GRAYSCALE); 
cv::Mat bw = img > 128;

在这种方式下,矩阵中所有大于128的像素现在都是白色的,而小于或等于128的像素将是黑色的。
可选地,并且对我来说效果不错的是应用模糊。
cv::blur( bw, bw, cv::Size(3,3) );

稍后,您可以按照之前的方法保存它:

cv::imwrite("image_bw.jpg", bw);

我不确定...我认为这取决于你要保存的图像类型。对于照片(我正在处理照片),我认为这是正确的格式。 - alvaropgl
1
JPEG的问题在于它会引入伪影并且会降低图片的质量。我建议使用PNG格式,或者对于非常小的文件可以使用带有CCITT Fax 4压缩的TIFF格式。 - user1741137
@user1741137,如何使用OpenCV将Mat保存为CCITT Fax 4压缩的TIFF图像?使用Highgui.imwrite(“sample.tiff”,binaryImage);我总是获得具有LZW压缩和8位色深度的TIFF图像 - [请参见我的问题](https://dev59.com/R4zda4cB1Zd3GeqPhhFJ)。 - Alexander Abakumov

1

我在我的博客文章中做了类似的事情。展示了一个简单的C++示例。

目标是使用开源cvBlobsLib库来检测印刷在微阵列玻片上的斑点样本,但是如你所提到的,图像必须从彩色转换为灰度,然后再转换为黑白才能实现这一目标。


我想看看你的这个作品:正如你所提到的,图像必须从彩色转换为灰度,然后再转换为黑白。谢谢。 - RidaSana
上面提到的链接无法使用,这个可以:链接 - Yeraze

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接