Foreword
In the previous article , we explained the threshold function in image processing. In this article we will do the expansion and corrosion functions.
Expansion and Corrosion
The concept may be difficult to explain. Let’s take a look at the pictures. The first is the original picture:
After expansion it will look like this:
After corrosion, it will look like this:
It may seem a little puzzling. It is obvious that it is expansion, but why the words become thinner, and it is obvious that it is corrosion, why does the word become thicker?
Actually, the so-called expansion should refer to :
Brighter color blocks expand.
The so-called corrosion should refer to :
Brighter color blocks corrode.
In the picture above, since the white background is a lighter color block, when it expands, it flattens the words on the darker black block... On the contrary, when it corrodes, the words absorb water and expand...
expressed as a mathematical formula is :
To put it bluntly, it is to find the darkest or brightest pixel in the kernel of a specified size, and replace the pixel on the kernel anchor point with this point.
Achieve
First we implement the expansion dilate function.
var dilate = function(__src, __size, __borderType, __dst ){
__src || error(arguments.callee, IS_UNDEFINED_OR_NULL/* {line} */);
if(__src.type && __src.type == "CV_RGBA"){
var width = __src .col,
height = __src.row,
size = __size || 3,
dst = __dst || new Mat(height, width, CV_RGBA),
dstData = dst.data;
var start = size >> 1;
var withBorderMat = copyMakeBorder(__src, start, start, 0, 0, __borderType),
mData = withBorderMat.data,
mWidth = withBorderMat.col;
var newOffset, total, nowX, offsetY, offsetI, nowOffset, i, j;
if(size & 1 === 0){
error(arguments .callee, UNSPPORT_SIZE/* {line} */);
return __src;
}
for(i = height; i--;){
offsetI = i * width;
for(j = width; j--;){
newOffset = 0;
total = 0;
for(y = size; y--;){
offsetY = ( y i) * mWidth * 4;
for(x = size; x--;){
nowX = (x j) * 4;
nowOffset = offsetY nowX;
(mData[nowOffset] mData [nowOffset 1] mData[nowOffset 2] > total) && (total = mData[nowOffset] mData[nowOffset 1] mData[nowOffset 2]) && (newOffset = nowOffset);
}
}
dstData[(j offsetI) * 4] = mData[newOffset];
dstData[(j offsetI) * 4 1] = mData[newOffset 1];
dstData[(j offsetI) * 4 2] = mData [newOffset 2];
dstData[(j offsetI) * 4 3] = mData[newOffset 3];
}
}
}else{
error(arguments.callee , UNSPPORT_DATA_TYPE/* {line} */);
}
return dst;
};
In this line of code, we first use the RGB value and the previous one Compare the maximum value total, and then if the new value is larger, assign the new value to total, and assign the new offset newOffset to the current offset nowOffset.
Then after the entire kernel-sized area is cycled, a maximum total and the corresponding offset newOffset can be found. You can assign the value:
dstData[(j offsetI) * 4] = mData[newOffset];
dstData[(j offsetI) * 4 1] = mData[newOffset 1];
dstData[(j offsetI) * 4 2 ] = mData[newOffset 2];
dstData[(j offsetI) * 4 3] = mData[newOffset 3];
Then the erosion function is the opposite, just find the smallest value.
var erode = function(__src, __size, __borderType, __dst){
__src || error(arguments.callee, IS_UNDEFINED_OR_NULL/* {line} */);
if(__src.type && __src.type == "CV_RGBA"){
var width = __src.col,
height = __src.row,
size = __size || 3,
dst = __dst || new Mat(height, width, CV_RGBA),
dstData = dst.data;
var start = size >> 1;
var withBorderMat = copyMakeBorder(__src, start, start, 0, 0, __borderType),
mData = withBorderMat.data,
mWidth = withBorderMat.col;
var newOffset, total, nowX, offsetY, offsetI, nowOffset, i, j;
if(size & 1 === 0){
error(arguments.callee, UNSPPORT_SIZE/* {line} */);
return __src;
}
for(i = height; i--;){
offsetI = i * width;
for(j = width; j--;){
newOffset = 0;
total = 765;
for(y = size; y--;){
offsetY = (y i) * mWidth * 4;
for(x = size; x--;){
nowX = (x j) * 4;
nowOffset = offsetY nowX;
(mData[nowOffset] mData[nowOffset 1] mData[nowOffset 2] < total) && (total = mData[nowOffset] mData[nowOffset 1] mData[nowOffset 2]) && (newOffset = nowOffset);
}
}
dstData[(j offsetI) * 4] = mData[newOffset];
dstData[(j offsetI) * 4 1] = mData[newOffset 1];
dstData[(j offsetI) * 4 2] = mData[newOffset 2];
dstData[(j offsetI) * 4 3] = mData[newOffset 3];
}
}
}else{
error(arguments.callee, UNSPPORT_DATA_TYPE/* {line} */);
}
return dst;
};
效果