《学习OpenCV 3(中文版)》 —不那么简单的变换

举报
清华大学出版社 发表于 2019/10/23 20:58:31 2019/10/23
【摘要】 本节书摘来自清华大学出版社《学习OpenCV 3(中文版)》 一书中第二章,作者是[美]安德里安 • 凯勒 (Adrian Kaehler) 加里 • 布拉德斯基 (Gary Bradski) , 阿丘科技 刘昌祥 吴雨培 王成龙 崔玉芳 等译。

不那么简单的变换

接下来,我们要了解如何做更多有意思的事情。在示例2-5中,我们没有任何特殊目的地使用了高斯模糊。现在我们将使用高斯模糊来对一张图像实现基2的降采样[Rosenfeld80]。如果我们对图像进行多次降采样,就要建立一个尺度空间(也称为“图像金字塔”),这一方法是计算机视觉用于处理传感器和目标尺度变化的常用手段之一。

对于那些了解信号处理和香农-奈奎斯特采样理论[Shannon49]的读者,对信号的降采样 (在本例中,我们创建一个图像并对每个像素进行采样)等效于和一系列脉冲函数进行卷积(将这些函数视为“峰值”)。这样的采样会把高频分量引入输出信号(图像)。为了避免这样的事情发生,我们希望首先通过一个高通滤波器来限制信号带宽,使其能够在采样频率之内。在OpenCV中,高斯模糊以及降采样通过cv::pyrDown()函数来实现,我们的实现在示例2-6中。

示例2-6:使用cv::pyrDown()来创建一个新的图像,其宽高均为原始图像的一半

#include <opencv2/opencv.hpp> int main( int argc, char** argv ) {   cv::Mat img1,img2;

  cv::namedWindow( "Example1", cv::WINDOW_AUTOSIZE );   cv::namedWindow( "Example2", cv::WINDOW_AUTOSIZE );

  img = cv::imread( argv[1] );   cv::imshow( "Example1", img1 );

  cv::pyrDown( img1, img2);   cv::imshow( "Example2", img2 );   cv::waitKey(0);   return 0;

};

然后,让我们来分析一段相似但更加复杂的代码,示例2-7这段代码包含有Canny边缘检测器[Canny86]cv::Canny()。在示例2-7中,边缘检测器通过cv::cvtColor()函数生成一个和原图一样大小但只有一个通道的图像,从而将图像从BGR图像转换为灰度图,这个操作在OpenCV中定义为宏cv::COLOR_BGR2GRAY。

示例2-7Canny边缘检测器输出一个单通道的(灰度)图像

#include <opencv2/opencv.hpp> int main( int argc, char** argv ) {

    cv::Mat img_rgb, img_gry, img_cny;

    cv::namedWindow( "Example Gray",  cv::WINDOW_AUTOSIZE );     cv::namedWindow( "Example Canny", cv::WINDOW_AUTOSIZE );     img_rgb = cv::imread( argv[1] );

    cv::cvtColor( img_rgb, img_gry, cv::COLOR_BGR2GRAY);     cv::imshow( "Example Gray", img_gry );

    cv::Canny( img_gry, img_cny, 10, 100, 3, true );     cv::imshow( "Example Canny", img_cny );     cv::waitKey(0);

}

这时,我们可以将很多简单的操作串联起来。比如说,如果我们想要收缩两次图像然后寻找收缩过两次的图像中的边缘,我们可以像示例2-8一样处理。

示例2-8:在一个简单图像处理流程中结合图像金字塔操作(两次)和Canny边缘检测器 cv::cvtColor( img_rgb, img_gry, cv::BGR2GRAY ); cv::pyrDown( img_gry, img_pyr ); cv::pyrDown( img_pyr, img_pyr2 );

cv::Canny( img_pyr2, img_cny, 10, 100, 3, true ); // do whatever with 'img_cny' //

...

在示例2-9中,我们展示了一个简单的方法来读写示例2-8的像素值。

示例2-9:读写示例2-8中的像素值

int x = 16, y = 32;

cv::Vec3b intensity = img_rgb.at< cv::Vec3b >(y, x);

// ( Note: We could write img_rgb.at< cv::Vec3b >(x,y)[0] )

// uchar blue  = intensity[0]; uchar green = intensity[1]; uchar red   = intensity[2];

std::cout << "At (x,y) = (" << x << ", " << y <<           "): (blue, green, red) = (" <<           (unsigned int)blue <<

          ", " << (unsigned int)green << ", " <<           (unsigned int)red << ")" << std::endl;

std::cout << "Gray pixel there is: " <<

             (unsigned int)img_gry.at<uchar>(y, x) << std::endl; x /= 4; y /= 4; 

std::cout << "Pyramid2 pixel there is: " <<

             (unsigned int)img_pyr2.at<uchar>(y, x) << std::endl; img_cny.at<uchar>(x, y) = 128; // Set the Canny pixel there to 128 


【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。