问题背景:一张未知图片,opencv读取进来,有几种情况都要分析
- 3通道----彩色:(123,146,78)(147,25,36)
- 3通道----灰度:(123,123,123)(45,45,45)
- 3通道----二值:(0,0,0)(255,255,255)
- 1通道----灰度:(123)(45)(67)(255)
- 1通道----二值:(0)(255)(0)(255)
找了半天,网上大多是废话,直方图方法什么的没用!(例如:(255,0,0)(0,255,0)(0,0,255)统计三通道结果一样,所以在某个特殊情况时,彩色图会误认为灰度图、二值图)
直接上代码(只要30ms就解决了),觉得好的记得点个赞:
子函数部分:
enum color_type
{
unknown_error = 0,
channel_3_color = 1,//3通道彩色
channel_3_gray = 2,//3通道灰度
channel_3_binary = 3,//3通道二值
channel_1_gray = 4,//1通道灰度
channel_1_binary = 5,//1通道二值
};
//1用各个通道进行矩阵对比
color_type Judge_color(cv::Mat img)
{
color_type color_flag;
if (!img.data)
return color_flag = unknown_error;
if (img.channels() == 3)//3通道
{
std::vector<cv::Mat> rgbChannels(3);
split(img, rgbChannels);
if (!countNonZero(rgbChannels[0] != rgbChannels[1]) && !countNonZero(rgbChannels[1] != rgbChannels[2]))//3通道完全相同
{
//非0.255个数=总数-0个数-255个数(化简后)
int num = countNonZero(rgbChannels[0]) + countNonZero(~rgbChannels[0]) - rgbChannels[0].rows*rgbChannels[0].cols;
if (num)//灰度
{
color_flag = channel_3_gray;
}
else//黑白
{
color_flag = channel_3_binary;
}
}
else//三通道不完全同,彩色图
{
color_flag = channel_3_color;
}
}
else if (img.channels() == 1)//1通道
{
int num = countNonZero(img) + countNonZero(~img) - img.rows*img.cols;
if (num)//灰度
{
color_flag = channel_1_gray;
}
else//黑白
{
color_flag = channel_1_binary;
}
}
return color_flag;
}
主函数测试代码:
int main()
{
cv::Mat source = cv::imread("3.png");
color_type flag = Judge_color(source);
Mat sourcep;
cv::resize(source, sourcep, Size(4000, 2000));
switch (flag)
{
case unknown_error:
break;
case channel_3_color:
break;
case channel_3_gray://三通道灰度--》单通道灰度
cvtColor(sourcep, sourcep, COLOR_BGR2GRAY);
break;
case channel_3_binary://三通道二值--》单通道二值
cvtColor(sourcep, sourcep, COLOR_BGR2GRAY);
threshold(sourcep, sourcep, 128, 255, THRESH_BINARY);
break;
case channel_1_gray:
break;
case channel_1_binary://单通道灰度--》转单通道二值
threshold(sourcep, sourcep, 128, 255, THRESH_BINARY);
break;
default:
break;
}
}