OpenCV Tutorials —— Mask operations on matrices

Mask operations on matrices are quite simple. The idea is that we recalculate each pixels value in an image according to a mask matrix (also known as kernel). This mask holds values that will adjust how much influence neighboring pixels (and the current pixel) have on the new pixel value

蒙版操作或者核操作 ~~

The first notation is by using a formula, while the second is a compacted version of the first by using a mask. You use the mask by putting the center of the mask matrix (in the upper case noted by the zero-zero index) on the pixel you want to calculate and sum up the pixel values multiplied with the overlapped matrix values.

 

void Sharpen(const Mat& myImage, Mat& Result)
{
    CV_Assert(myImage.depth() == CV_8U);  // accept only uchar images

    Result.create(myImage.size(), myImage.type());
    const int nChannels = myImage.channels();

    for(int j = 1; j < myImage.rows - 1; ++j)
    {
        const uchar* previous = myImage.ptr<uchar>(j - 1);	// 前一行
        const uchar* current  = myImage.ptr<uchar>(j    );	// 当前行
        const uchar* next     = myImage.ptr<uchar>(j + 1);  // 后一行

        uchar* output = Result.ptr<uchar>(j);

        for(int i = nChannels; i < nChannels * (myImage.cols - 1); ++i)
        {
            *output++ = saturate_cast<uchar>(5 * current[i]
                         -current[i - nChannels] - current[i + nChannels] - previous[i] - next[i]);
        }
    }

    Result.row(0).setTo(Scalar(0));
    Result.row(Result.rows - 1).setTo(Scalar(0));
    Result.col(0).setTo(Scalar(0));
    Result.col(Result.cols - 1).setTo(Scalar(0));
}

We’ll use the plain C [] operator to access pixels. Because we need to access multiple rows at the same time we’ll acquire the pointers for each of them (a previous, a current and a next line). We need another pointer to where we’re going to save the calculation.

 

Border

On the borders of the image the upper notation results inexistent pixel locations (like minus one - minus one). In these points our formula is undefined. A simple solution is to not apply the kernel in these points and, for example, set the pixels on the borders to zeros:

Result.row(0).setTo(Scalar(0));               // The top row
Result.row(Result.rows - 1).setTo(Scalar(0)); // The bottom row
Result.col(0).setTo(Scalar(0));               // The left column
Result.col(Result.cols - 1).setTo(Scalar(0)); // The right column

setTo (Scalar) —— 将矩阵置为某一元素

 

The filter2D function

上面的方式,自己实现了整个过滤过程 —— 其实可以把公共部分代码提取出来

For this you first need to define a Mat object that holds the mask:

Mat kern = (Mat_<char>(3,3) <<  0, -1,  0,
                               -1,  5, -1,
                                0, -1,  0);

Then call the filter2D function specifying the input, the output image and the kernell to use:

filter2D(I, K, I.depth(), kern);

The function even has a fifth optional argument to specify the center of the kernel, and a sixth one for determining what to do in the regions where the operation is undefined (borders).

这种方式更加简洁,并且比硬编码的方式效率更高

滤波的方法非常常用,而且不同mask的不同效果应该熟悉

 

#include "stdafx.h"

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

using namespace std;
using namespace cv;

static void help(char* progName)
{
	cout << endl
		<<  "This program shows how to filter images with mask: the write it yourself and the"
		<< "filter2d way. " << endl
		<<  "Usage:"                                                                        << endl
		<< progName << " [image_name -- default lena.jpg] [G -- grayscale] "        << endl << endl;
}

void Sharpen(const Mat& myImage,Mat& Result);

int main( int argc, char* argv[])
{
	help(argv[0]);
	const char* filename = argc >=2 ? argv[1] : "lena.jpg";

	Mat I, J, K;

	if (argc >= 3 && !strcmp("G", argv[2]))
		I = imread( filename, CV_LOAD_IMAGE_GRAYSCALE);
	else
		I = imread( filename, CV_LOAD_IMAGE_COLOR);

	namedWindow("Input", WINDOW_AUTOSIZE);
	namedWindow("Output", WINDOW_AUTOSIZE);

	imshow("Input", I);
	double t = (double)getTickCount();

	Sharpen(I, J);

	t = ((double)getTickCount() - t)/getTickFrequency();
	cout << "Hand written function times passed in seconds: " << t << endl;

	imshow("Output", J);
	waitKey(0);

	Mat kern = (Mat_<char>(3,3) <<  0, -1,  0,
		-1,  5, -1,
		0, -1,  0);
	t = (double)getTickCount();
	filter2D(I, K, I.depth(), kern );
	t = ((double)getTickCount() - t)/getTickFrequency();
	cout << "Built-in filter2D time passed in seconds:      " << t << endl;

	imshow("Output", K);

	waitKey(0);
	return 0;
}
void Sharpen(const Mat& myImage,Mat& Result)
{
	CV_Assert(myImage.depth() == CV_8U);  // accept only uchar images

	const int nChannels = myImage.channels();
	Result.create(myImage.size(),myImage.type());

	for(int j = 1 ; j < myImage.rows-1; ++j)
	{
		const uchar* previous = myImage.ptr<uchar>(j - 1);
		const uchar* current  = myImage.ptr<uchar>(j    );
		const uchar* next     = myImage.ptr<uchar>(j + 1);

		uchar* output = Result.ptr<uchar>(j);

		for(int i= nChannels;i < nChannels*(myImage.cols-1); ++i)
		{
			*output++ = saturate_cast<uchar>(5*current[i]
			-current[i-nChannels] - current[i+nChannels] - previous[i] - next[i]);
		}
	}

	Result.row(0).setTo(Scalar(0));
	Result.row(Result.rows-1).setTo(Scalar(0));
	Result.col(0).setTo(Scalar(0));
	Result.col(Result.cols-1).setTo(Scalar(0));
}
时间: 2024-11-05 11:48:41

OpenCV Tutorials —— Mask operations on matrices的相关文章

学习opencv tutorials

1.opencv里头动态库和静态库的区别 lib是动态库,staticlib是静态库. 这是opencv tutorials中对动态库和静态库的说明.动态库是在runtime时候才load的库文件.而静态库文件会在你build的时候build-in inside your exe file.优点是可以避免误删,缺点是应用程序变大,加载时间也会变长. 2.  Visual Studio中solution和project的关系 在VS中,一个solution中可以包含多个project. 3.  两

OpenCV Tutorials &mdash;&mdash; Basic Thresholding Operations

  Threshold Binary This thresholding operation can be expressed as: So, if the intensity of the pixel is higher than , then the new pixel intensity is set to a . Otherwise, the pixels are set to . 二分 ~~ 阈值化最朴素的形式   Threshold Binary, Inverted This thr

OpenCV Tutorials &mdash;&mdash; Making your own linear filters

kernel A kernel is essentially a fixed size array of numerical coefficeints along with an anchor point in that array, which is tipically located at the center. The value of the convolution is calculated in the following way: 1,Place the kernel anchor

OpenCV Tutorials &mdash;&mdash; Mat

if you pass on an already existing Mat object, which has already allocated the required space for the matrix, this will be reused. The idea is that each Mat object has its own header, however the matrix may be shared between two instance of them by h

OpenCV Tutorials &mdash;&mdash; Interoperability with OpenCV 1

新版本的OpenCV 使用Mat作为基本的图像容器,而代替旧版本的 CvMat 和 IplImage All the OpenCV related stuff is put into the cv namespace to avoid name conflicts with other libraries data structures and functions. Therefore, either you need to prepend the cv:: keyword before eve

OpenCV Tutorials &mdash;&mdash; Back Projection

反向投影 一种记录给定图像中的像素点如何适应直方图模型像素分布的方式. 反向投影就是首先计算某一特征的直方图模型,然后使用模型去寻找图像中存在的该特征. backproject是直接取直方图中的值,即以灰度为例,某种灰度值在整幅图像中所占面积越大,其在直方图中的值越大,backproject时,其对应的像素的新值越大(越亮),反过来,某灰度值所占面积越小,其新值就越小. 源图像 --> 直方图 --> backproject图像   calcBackProjectPatch,整个是基于块的形式

OpenCV Tutorials &mdash;&mdash; Scan images

color space reduction divide the color space current value with a new input value to end up with fewer colors. For instance every value between zero and nine takes the new value zero, every value between ten and nineteen the value ten and so on. 减少颜色

OpenCV Tutorials &mdash;&mdash; Histogram Calculation

Let's identify some parts of the histogram: 1,dims: The number of parameters you want to collect data of. 2,bins: It is the number of subdivisions in each dim. 3,range: The limits for the values to be measured. void calcHist(const Mat* images, int ni

OpenCV Tutorials &mdash;&mdash; File Input and Output using XML and YAML files

They are two kinds of data structures you may serialize: mappings(like the STL map) and element sequence (like the STL vector>. The difference between these is that in a map every element has a unique name through what you may access it. For sequence