【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
我们在使用opencv的时候,虽然大部分算法都不需要我们自己重头开始编写,但是总有一些关于我们自己产品的know-how,是之前库里本来就不存在的。所以,这个时候,我们还是希望能够借助于opencv实现一些自定义的算法,这样可以满足客户个性化的需求,也可以提高自己的竞争力。另外,即使是opencv库里面已经有的算法,由于它本身面对的是通用平台,因此很难对相关代码进行专门的硬件优化,所以即使是已经存在的算法,有的时候还是需要重新写一遍,出一个针对专门硬件的加速版本,这都是常有的事情。
1、复用之前的opencv部署步骤
一开始,我们还是需要创建一个console工程、配置好include目录、配置好lib目录、拷贝好必要的dll文件、准备好测试图片,这些都是少不了的。由于这些内容之前都已经谈到过,所以,这里不再赘述。
2、编写自定义函数
编写自定义函数的核心主要有三个,第一,相关的数据结构是什么?很明显,在opencv下面,数据的保存方式就是cv::Mat。第二,怎么获取像素值?一般来说,直接使用image.at<uchar>(i,j)的方式,就可以获得像素值。第三,怎么设置像素值,做法和第二点一样,不同的是前面是读取,这个直接赋值给它即可。所以,如果我们需要用它来写一个简单的二值化函数,一般可以这么来做,
#include <opencv2/opencv.hpp>
#include <iostream>
// self defined image processing function
void customThreshold(const cv::Mat& inputImage, cv::Mat& outputImage, int thresholdValue)
{
// make sure this is single channel
CV_Assert(inputImage.channels() == 1);
// copy image
outputImage = inputImage.clone();
// loop to check each pixel
for (int i = 0; i < outputImage.rows; ++i)
{
for (int j = 0; j < outputImage.cols; ++j)
{
// get value
uchar pixelValue = outputImage.at<uchar>(i, j);
// set value
outputImage.at<uchar>(i, j) = (pixelValue > thresholdValue) ? 255 : 0;
}
}
}
3、补充完剩余的图像处理代码
仅仅有customThreshold函数还是不够的,整个项目要想运行起来,还需要读取图片文件、保存图片文件、显示图片文件等内容。所以,我们继续把相关的代码补上即可,
// file starts here
int main()
{
// read image
cv::Mat image = cv::imread("D:/lena.png");
// check if image has been loaded successfully
if (image.empty())
{
std::cout << "unable to load image here" << std::endl;
return -1;
}
// transfer image to gray type
cv::Mat grayImage;
cv::cvtColor(image, grayImage, cv::COLOR_BGR2GRAY);
// transfer gray image to binary image
cv::Mat binaryImage;
customThreshold(grayImage, binaryImage, 110);
// show binary image
cv::imshow("Binary Image", binaryImage);
// wait for input
cv::waitKey(0);
return 0;
}
首先,还是和以前一样,通过cv::imread的方法读取图片。接着判断图片是否为空。判断结束后,先是把image转成grayImage,然后把grayImage继续转成binaryImage,最后显示binaryImage即可。当然,这里会调用一下cv::waitKey,没有按键输入的话,图片窗口会一直处于显示状态。
4、编译和测试
编译的话,主要看编译有没有出错、链接有没有出错、运行有没有出错,如果这几个部分都没有问题,那说明我们前面设置的环境都是ok的。这样,只需要看显示的图片有没有变成二值化即可。另外,也说明我们在完全没有借助opencv api的情况下,自己实现了一个自定义函数,这在后续的产品开发中是非常有用的。