Day 7 - Opencv 对连续图像的高速扫描

本文探讨了如何通过检查图像连续性和使用低层次指针算法来提高OpenCV处理图像的性能。通过在图像行末填充以达到内存对齐,可以优化处理速度。在代码示例中展示了减色算法,如果图像连续,可以使用reshape和指针操作遍历图像,减少循环次数,从而提升效率。此外,还介绍了如何通过image.isContinuous()函数判断图像是否已填充。
摘要由CSDN通过智能技术生成

Day 7 - Opencv 对连续图像的高速扫描

1.前言

为了提高性能,可以在图像的每行末尾用额外的像素填充到某个数字的整数倍,例如8,图像处理的性能可能会提高,因此最好根据内存配置情况将数据对齐。若去掉填充后,图像仍可看作是W*H像素的长一维数组。

//检查矩阵是否连续
//检查行的长度(字节数)与“列的个数*单个像素的字节数”是否相等
image.step == image.cols * image.elemSize();

还有另一种方式也可以检查图像矩阵是否被填充:

cv::Mat的 isContinuous

利用这些,在出一些特殊的处理算法中,我们就可以充分利用图像的连续性,在单个循环内来处理图像。

2. 代码

#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <random>
#include <iostream>

//减色函数
void reduceColor(cv::Mat image, int n);

int main(int argc, char** argv)
{
	cv::Mat image = cv::imread("15011.jpg");
	if (image.empty())
	{
		std::cout << "\n Durn, couldn't read image filename " << std::endl;
		return 1;
	}
	cv::namedWindow("Original Image");
	cv::imshow("Original Image", image);

	auto startTime = std::chrono::system_clock::now();
	reduceColor(image, 32);
	auto endTime = std::chrono::system_clock::now();
	std::cout << "time:" << std::chrono::duration_cast<std::chrono::microseconds>(endTime - startTime).count() << std::endl;
	cv::namedWindow("ReducedColr Image");
	cv::imshow("ReducedColr Image", image);
	cv::waitKey(0);
	return 0;
}


//image: 输入图像
//div    : 减色因子
void reduceColor(cv::Mat image, int div)
{
	if (image.isContinuous())  //判断图像是否被填充
	{		
		//对矩阵的行和列进行重组
		image = image.reshape(1,  //通道数 
			1); //行数
	}

	int rows = image.rows; //行,高度
	int cols = image.cols; //列,宽度
	int allCols = cols * image.channels();//每行的元素总数

	double nTemp = std::log(static_cast<double>(div)) / std::log(2.0); //求解给定div下的n值 div = pow(2, n);
	int n = static_cast<int>(nTemp + 0.5); //0.5相当于四舍五入

	//掩码,求div的倍数
	uchar mask = 0xFF << n;

	//对每个元素进行遍历
	for (int i = 0; i < rows; i++) //行遍历
	{
		uchar* data = image.ptr<uchar>(i); //获取行的首地址
		for (int j = 0; j < allCols; j++) //列遍历
		{

			*data &= mask; //掩码运算
			*data++ += div >> 1;
		}
	}
}

注:opencv中的reshape之后,似乎可以不用再reshape回来,因为结果可以直接显示。
在这里插入图片描述

3.低层次指针算法

从图像的起点开始循环:

uchar* data = image.data;

从一行移动到下一行

data += image.step;//下一行

通过下面的方法得到第j行第i列的像素的地址:

data = image.daa + j * image.step + i * image.elemSize();

但是并不推荐使用这种方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值