嵌入式人工智能应用
嵌入式人工智能应用-第三章 opencv操作 5 二值化
1 二值化
1.1 概念介绍
二值化是图像分割的一种重要方法,图像的二值化就是将图像的表示方法缩减成两种状态,要么是 0,要么是 1,对于肉眼看到的就是非黑即白。一幅彩色图像,比如是 RGB888 的,则有 R/G/B 三个通道,每个通道的位深都是 8,所以 R、G、B 都有 0 到 255 的变化空间,表现出来的就是 256 种颜色。三个通道柔和在一起表示一个像素点,就有 224 种颜色。灰度图像是将 RGB 三个通道缩减到一个通道,于是他的变化空间就是 0 到 255,也就是 256 种颜色。二值图像就是将变化范围缩减到 0 到 1,也就是 2 种颜色。
图像处理中非常重要的一步,尤其在图像分析、物体识别、边缘检测中经常用到。
1.2 函数介绍
cv::threshold 是 OpenCV 中用于图像二值化的一个非常重要的函数。它可以将图像中的像素值根据给定的阈值进行分类,并将结果映射为两个值(通常是黑或白)。这个函数不仅支持简单的阈值处理,还支持一些先进的二值化算法。
cv::threshold(
const cv::Mat& src, // 输入图像
cv::Mat& dst, // 输出图像
double thresh, // 阈值(如果是 Otsu 等方法,这个值会被自动计算)
double maxValue, // 设定的最大值,通常是255
int thresholdType // 阈值类型(例如 THRESH_BINARY, THRESH_OTSU 等)
);
参数解释:
src:输入图像,必须是灰度图(CV_8UC1)。
dst:输出图像,和输入图像大小相同,存储二值化后的结果。
thresh:阈值,决定哪些像素变成白色,哪些变成黑色。
maxValue:最大值,一般设为 255,表示白色。
thresholdType:阈值类型(有多种选择,下面会详细介绍)
阈值类型 说明
THRESH_BINARY 如果像素值大于阈值,输出最大值(如 255),否则输出 0(黑色)。
THRESH_BINARY_INV 与 THRESH_BINARY 相反,像素值大于阈值的变为 0(黑),小于阈值的变为最大值(白)。
THRESH_TRUNC 如果像素值大于阈值,则将该像素值设置为阈值;否则不改变。
THRESH_TOZERO 如果像素值大于阈值,保留原值;否则将其设为 0(黑色)。
THRESH_TOZERO_INV 与 THRESH_TOZERO 相反,像素值小于阈值时保留原值,其他设置为 0(黑)。
THRESH_OTSU 自适应阈值选择方法。该方法通过最大化类间方差来选择最佳的阈值(无需手动设置阈值)。
THRESH_TRIANGLE 基于最大类间方差的阈值选择方法,类似 Otsu,但一般使用自适应的三角形方法。
1.2 基本应用
cv::Mat grayImage = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE);
cv::Mat binaryImage;
cv::threshold(grayImage, binaryImage, 128, 255, cv::THRESH_BINARY);
// Otsu 二值化
cv::Mat otsuImage;
cv::threshold(grayImage, otsuImage, 0, maxValue, cv::THRESH_BINARY | cv::THRESH_OTSU);
1.3 参考案例
代码将一幅灰度图像进行二值化,然后显示出来。使用 OpenCV 提供的 Mat 定义两个变量,用于存储原始图像和二值化后的图像,OpenCV 提供的 imread 方法可以直接读取灰度图像,第二个参数 flag 默认是1,设置成 0 即可读取灰度图像。使用 OpenCV 提供的 threshold 方法进行二值化处理,处理结果存放在第二个参数 result 中。
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
using namespace cv;
using namespace std;
int main(int argc,char* argv[])
{
Mat img;
Mat result;
img = imread("cyq.jpg",0);
namedWindow("Image");
imshow("Image", img);
threshold(img, result, 100, 255, CV_THRESH_BINARY);
imshow("output", result);
waitKey(0);
return 0;
}
2 图像缩放
2.1 基本概念
在计算机图像处理和计算机图形学中,图像缩放(image scaling)是指对数字图像的大小进行调整的过程。图像缩放是一种非平凡的过程,需要在处理效率以及结果的平滑度(smoothness)和清晰度(sharpness)上做一个权衡。当一个图像的大小增加之后,组成图像的像素的可见度将会变得更高,从而使得图像表现得粗糙。相反地,缩小一个图像将会增强它的平滑度和清晰度,让图像看起来更加细腻。OpenCV 提供的 Resize() 函数非常方便而且效率也非常高。
图像缩放是计算机视觉中一个非常常见的操作。它涉及到改变图像的尺寸,可以用来适应不同的显示设备、节省存储空间,或者为了某些处理操作(比如特征提取、物体检测等。
2.2 函数介绍
cv::resize(
const cv::Mat& src, // 输入图像
cv::Mat& dst, // 输出图像
cv::Size dsize, // 输出图像的尺寸,指定宽度和高度
double fx = 0, // 水平缩放因子(默认0,表示不改变)
double fy = 0, // 垂直缩放因子(默认0,表示不改变)
int interpolation = cv::INTER_LINEAR // 插值方法,默认线性插值
);
src:输入图像(可以是彩色图像或灰度图像)。
dst:输出图像,存储缩放后的结果。
dsize:目标图像的大小(cv::Size(width, height)),你可以指定宽度和高度。
fx、fy:缩放因子。如果你不指定 dsize,可以通过这两个因子来控制宽度和高度的缩放比例。例如,fx = 2 表示宽度放大2倍,fy = 0.5 表示高度缩小为原来的一半。
interpolation:插值方法,用于在缩放过程中生成新的像素值。OpenCV 支持多种插值方法,默认是 线性插值(cv::INTER_LINEAR)。
cv::INTER_NEAREST:最近邻插值。最快,但质量较差,可能导致“锯齿状”边缘。
cv::INTER_LINEAR:双线性插值。常用的默认方法,平衡速度和质量,适用于大多数场景。
cv::INTER_CUBIC:三次插值。效果更好,但速度稍慢,适合对质量要求较高的场景。
cv::INTER_LANCZOS4:Lanczos插值。最优的质量,但计算量最大,适用于高质量要求的缩放。
2.3 基本参考代码
#include <opencv2/opencv.hpp>
#include <iostream>
int main() {
// 读取图像
cv::Mat image = cv::imread("image.jpg");
if (image.empty()) {
std::cerr << "无法读取图像!" << std::endl;
return -1;
}
// 创建一个目标大小
cv::Size targetSize(800, 600); // 将图像缩放到 800x600
// 输出图像
cv::Mat resizedImage;
// 使用 cv::resize 进行图像缩放
cv::resize(image, resizedImage, targetSize, 0, 0, cv::INTER_LINEAR);
// 显示原图和缩放后的图像
cv::imshow("原图", image);
cv::imshow("缩放后的图像", resizedImage);
cv::waitKey(0); // 等待用户按键
return 0;
}
cv::Mat resizedImage;
cv::resize(image, resizedImage, cv::Size(), 0.5, 0.5, cv::INTER_LINEAR); // 缩小到原来的一半
2.4 pyrUp 和 pyrDown 函数
pyrUp 和 pyrDown 是 OpenCV 中常用的图像金字塔(Pyramid)操作函数,用于分别对图像进行上采样和下采样。这两个函数是高效实现金字塔图像缩放的工具,通常用于多尺度图像处理,如图像金字塔、图像金字塔加速的图像匹配和特征提取等。
图像金字塔是一种多层次的图像表示方法,它将图像通过不同的分辨率进行降采样和上采样,形成一个金字塔结构。每一层都是前一层的缩小或放大的版本。
金字塔下采样(PyrDown):逐渐降低图像的分辨率,形成越来越小的图像。
金字塔上采样(PyrUp):逐渐提高图像的分辨率,形成越来越大的图像。
2.5 函数介绍
- cv::pyrDown 用于图像的 下采样(缩小),它通过 高斯滤波 平滑图像,然后对其进行 降采样。
cv::pyrDown(const cv::Mat& src, cv::Mat& dst, cv::Size dstsize = cv::Size());
src:输入图像。
dst:输出图像(下采样后的图像)。
dstsize:输出图像的目标尺寸。如果不指定,OpenCV 会自动计算。
默认情况下,目标图像的尺寸是源图像尺寸的一半(宽和高分别缩小为原来的一半)。
- cv::pyrUp 用于图像的 上采样(放大),它首先会通过 插值 放大图像,然后进行 高斯平滑 来减少模糊。
cv::pyrUp(const cv::Mat& src, cv::Mat& dst, cv::Size dstsize = cv::Size());
src:输入图像。
dst:输出图像(上采样后的图像)。
dstsize:输出图像的目标尺寸。如果不指定,OpenCV 会自动计算。
默认情况下,目标图像的尺寸是源图像尺寸的两倍(宽和高分别增大为原来的两倍)。
功能:
将图像的大小放大一倍,并通过高斯滤波对图像进行平滑,防止在放大过程中产生锯齿和过度模糊。
2.6 参考代码
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
using namespace cv;
Mat src, dst, tmp;
const char* window_name = "Pyramids Demo";
int main( int argc, char** argv )
{
printf( "\n Zoom In-Out demo \n " );
printf( "------------------ \n" );
printf( " * [u] -> Zoom in \n" );
printf( " * [d] -> Zoom out \n" );
printf( " * [ESC] -> Close program \n \n" );
src = imread( "cyq.jpg" );
if( !src.data ){
printf(" No data! -- Exiting the program \n");
return -1;
}
tmp = src;
dst = tmp;
namedWindow( window_name, CV_WINDOW_AUTOSIZE );
imshow( window_name, dst );
while( true )
{
int c;
c = waitKey(10);
if( (char)c == 27 )
break;
if( (char)c == 'u' ){
pyrUp( tmp, dst, Size( tmp.cols*2, tmp.rows*2 ) );
printf( "** Zoom In: Image x 2 \n" );
}
else if( (char)c == 'd' ) {
yrDown( tmp, dst, Size( tmp.cols/2, tmp.rows/2 ) );
printf( "** Zoom Out: Image / 2\n");
}
imshow( window_name, dst );
tmp = dst;
}
return 0;
}
2.7 总结
🔧 resize 是你万能的图像尺寸调节器;
📉 pyrDown 是模糊又平滑的降采样器;
📈 pyrUp 是温柔的图像放大器(带模糊,不够清晰)