javascript 이미지 처리 - 가장자리 기울기 계산 기능_javascript 기술

WBOY
풀어 주다: 2016-05-16 17:43:46
원래의
1479명이 탐색했습니다.
머리말

이전 글에서는 이미지 처리에서의 확장 및 침식 기능에 대해 설명했습니다. 이번 글에서는 가장자리 기울기 계산 기능을 수행하겠습니다.

이미지 가장자리

이미지의 가장자리는 수학적으로 어떻게 표현되나요?

How intensity changes in an edge

이미지 가장자리에서 인접한 픽셀 값이 크게 변경되어야 합니다. 수학에서 도함수는 변화의 속도를 표현하는 방법입니다. 그라데이션 값의 큰 변화는 이미지 내용의 중요한 변화를 나타냅니다.

더 생생한 이미지로 설명하기 위해 1차원 그래프가 있다고 가정하겠습니다. 아래 이미지에서 회색 값의 "점프"는 가장자리가 있음을 나타냅니다.

 Intensity Plot for an edge

1차 미분 파생을 사용하면 가장자리 "점프"(여기서는 높은 피크로 표시됨)의 존재를 더 명확하게 확인할 수 있습니다.

 First derivative of Intensity - Plot for an edge

이를 통해 이웃보다 그라데이션 값이 큰 픽셀을 찾아 가장자리를 찾을 수 있다는 결론을 내릴 수 있습니다.

대략적인 그라데이션

예를 들어 코어가 3개인 경우.

먼저 x 방향의 대략적인 도함수를 계산합니다.

G_{x} = begin{bmatrix}-1 & 0 &  1 \-2 & 0 &  2 \-1 & 0 &  1end{bmatrix} * I

그런 다음 y 방향에 대한 대략적인 도함수를 계산합니다.

G_{y} = begin{bmatrix}-1 & -2 & -1 </P> & 0 & 0 \ 1 &  2 &  1end{bmatrix} * I

그런 다음 기울기를 계산합니다.

G = sqrt{ G_{x}^{2}   G_{y}^{2} }

물론 다음과 같이 쓸 수도 있습니다.

G = |G_{x}|   |G_{y}|

함수 구현
코드는 다음과 같습니다.


var Sobel = function(__src, __xorder, __yorder, __size, __borderType, __dst){
(__src && (__xorder ^ __yorder)) || error(arguments.callee, IS_UNDEFINED_OR_NULL/* { line} * /)
if(__src.type && __src.type === "CV_GRAY"){
var kernel1,
kernel2,
height = __src.row,
width = __src.col,
dst = __dst || new Mat(height, width, CV_16I, 1),
dstData = dst.data
size = __size || 3; {
사례 1:
크기 = 3;
사례 3:
if(__xorder){
커널 = [-1, 0, 1,
-2, 0, 2 ,
-1, 0, 1
];
}else if(__yorder){
kernel = [-1, -2, -1,
, 0, 0,
, 2 , 1
];
}
break;
사례 5:
if(__xorder){
커널 = [-1, -2, 0, 2, 1 ,
-4, -8, 0, 8, 4,
-6,-12, 0,12, 6,
-4, -8, 0, 8, 4,
- 1, - 2, 0, 2, 1
]
}else if(__yorder){
커널 = [-1, -4, -6, -4, -1,
- 2, - 8,-12, -8, -2,
, 0, 0, 0, 0,
, 8, 12, 8, 2,
, 4, 6, 4, 1
] ;
}
break;
기본값:
error(arguments.callee, UNSPPORT_SIZE/* {line} */)

GRAY216IC1Filter(__src , 크기, 높이, 너비, 커널, dstData, __borderType);

}else{
error(arguments.callee, UNSPPORT_DATA_TYPE/* {line} */)
}
return dst;
};


여기에는 커널 크기가 3과 5인 Sobel 연산자만 제공됩니다. 주된 이유는 7 이상의 커널에 대한 계산이 상대적으로 느리기 때문입니다.
단일 채널 16비트 부호 있는 정수 행렬을 출력합니다.


코드 복사 코드는 다음과 같습니다.

function GRAY216IC1Filter(__src, size, height, width, kernel, dstData, __borderType){
var start = size >>

var withBorderMat = copyMakeBorder(__src, 시작, 시작, 0, 0, __borderType);

var mData = withBorderMat.data,
mWidth = withBorderMat.col

var i, j, y, x, c;
var newValue, nowX, offsetY, offsetI;

for(i = 높이; i--;){
offsetI = i * 너비
for(j = 너비; j- -;){
newValue = 0;
for(y = 크기; y--;){
offsetY = (y i) * mWidth; ){
nowX = x j;
newValue = (mData[offsetY nowX] * kernel[y * size x])
}
}
dstData[j offsetI] =
}
}
}

그런 다음 이 필터에 커널과 행렬을 주면 괜찮습니다.
이 필터를 독립적으로 만드는 이유는 Laplacian 및 Scharr 연산자와 같은 다른 유사한 계산 Edge 함수에 사용할 수 있기 때문입니다.

부호 없는 8비트 정수로 변환 소벨 연산자는 16비트 부호 있는 정수를 계산하므로 그림으로 표시할 수 없으므로 이를 부호 없는 8비트 정수 행렬로 변환하는 함수가 필요합니다.


convertScaleAbs 함수는 각 요소의 절대값을 가져와 Int8Array 배열에 넣습니다. 255보다 큰 숫자는 할당 중에 자동으로 255로 변환되고, 0보다 작은 숫자는 자동으로 0으로 변환됩니다. 그래서 우리는 이 작업을 처리하기 위한 함수를 만들 필요가 없습니다.

코드 복사 코드는 다음과 같습니다.
function ConvertScaleAbs(__src, __dst){
__src || error(arguments.callee, IS_UNDEFINED_OR_NULL/* {line} */);
var height = __src.row,
width = __src.col,
channel = __src.channel,
sData = __src.data;

if(!__dst){
if(채널 === 1)
dst = new Mat(높이, 너비, CV_GRAY)
else if(채널 === 4)
dst = new Mat(높이, 너비, CV_RGBA);
else
dst = new Mat(높이, 너비, CV_8I, 채널)
}else{
dst = __dst;
}

var dData = dst.data;

var i, j, c; --; ){
for(j = 너비 * 채널; j--;){
dData[i * 너비 * 채널 j] = Math.abs(sData[i * 너비 * 채널 j]);
}
}

return dst;
}



비례적으로 값 병합
또한 x 방향 기울기 계산 값과 y 방향 기울기 계산 값을 중첩하는 기능이 필요합니다.


코드 복사 코드는 다음과 같습니다.var addWeighted = function(__src1, __alpha, __src2, __beta , __gamma, __dst){
(__src1 && __src2) || error(arguments.callee, IS_UNDEFINED_OR_NULL/* {line} */)
var height = __src1.row,
width = __src1.col ,
alpha = __alpha || 0,
beta = __beta || 0,
channel = __src1.channel,
if(height ! == __src2 .row || 너비 !== __src2.col || 채널 !== __src2.channel){
error(arguments.callee, "Src2는 src1과 크기 및 채널 번호가 동일해야 합니다!"/* {line} */);
return null;
}

if(!__dst){
if(__src1.type.match(/CV_d /))
dst = new Mat( 높이, 너비, __src1.깊이(), 채널);
else
dst = new Mat(높이, 너비, __src1.깊이())
}else{
dst = __dst;
}

var dData = dst.data,
s1Data = __src1.data,
s2Data = __src2.data;

var i; 🎜>for (i = 높이 * 너비 * 채널; i--;)
dData[i] = __alpha * s1Data[i] __beta * s2Data[i] gamma;

return dst; >};


이 함수는 실제로 두 행렬의 해당 요소를 고정된 비율로 추가합니다.
렌더링



관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿