OpenCV 는 부동 소수점 데이터 의 시차 그림 에서 작은 얼룩 을 분할 하고 걸 러 냅 니 다.

OpenCV 는 BM 매 칭 방법 에서 매우 유용 한 함 수 를 제공 합 니 다.filter Speckles()는 시차 도 에서 작은(심지어 붙 어 있 는)얼룩 을 직접 제거 하 는 데 사 용 됩 니 다.그러나 이 함 수 는 디자인 초기 에 BM 알고리즘 에서 만 사용 하기 위해 서 였 을 수도 있 습 니 다.그래서 안 타 깝 게 도 이 함수 의 인 터 페 이 스 는 디자인 에 있어 서 CV 만 받 을 수 있 습 니 다.8UC 와 CV16SC 두 가지 데이터 형식의 시차 이미지 라 는 점 은 OpenCV 매 뉴 얼 에 명확 하 다.
그리고 입체 시각 원 리 를 바탕 으로 하 는 높 은 정밀도 측정 에서 우리 가 사용 하 는 시차 도 는 모두 CV 이다.32F 형식의 데 이 터 는 얼룩 을 걸 러 내기 위해 그림 변환 데 이 터 를 한 번 더 옮 겨 다 니 면 다소 쓸데없는 행동 이지 만 어 쩔 수 없다.
그래서 필 자 는 이 인터페이스 방법의 내부 실현 을 찾 았 다.기 쁜 발견 은 바 텀 실현 에서 데이터 의 유형 을 제한 하지 않 았 기 때문에 흥 이 나 서 바 텀 코드 를 옮 겨 서 인 터 페 이 스 를 다시 정의 하여 이 방법 을 더 많은 데이터 유형의 시차 도 에 적용 할 수 있 도록 했다.그래서 코드 를 실현 하기 위해 참고 만 할 수 있다.
typedef cv::Point_ Point2s;

template 
void FilterSpeckles(Mat& img, int maxSpeckleSize, float maxDiff)
{
	using namespace cv;

	int newVal = img.cols;

	cv::Mat _buf;

	int width = img.cols, height = img.rows, npixels = width*height;
	size_t bufSize = npixels*(int)(sizeof(Point2s) + sizeof(int) + sizeof(uchar));
	if (!_buf.isContinuous() || !_buf.data || _buf.cols*_buf.rows*_buf.elemSize() < bufSize)
		_buf.create(1, (int)bufSize, CV_8U);

	uchar* buf = _buf.data;
	int i, j, dstep = (int)(img.step / sizeof(T));
	int* labels = (int*)buf;
	buf += npixels*sizeof(labels[0]);
	Point2s* wbuf = (Point2s*)buf;
	buf += npixels*sizeof(wbuf[0]);
	uchar* rtype = (uchar*)buf;
	int curlabel = 0;

	// clear out label assignments
	memset(labels, 0, npixels*sizeof(labels[0]));

	for (i = 0; i < height; i++)
	{
		T* ds = img.ptr(i);
		int* ls = labels + width*i;

		for (j = 0; j < width; j++)
		{
			if (ds[j] != newVal)   // not a bad disparity
			{
				if (ls[j])     // has a label, check for bad label
				{
					if (rtype[ls[j]]) // small region, zero out disparity
						ds[j] = (T)newVal;
				}
				// no label, assign and propagate
				else
				{
					Point2s* ws = wbuf; // initialize wavefront
					Point2s p((short)j, (short)i);  // current pixel
					curlabel++; // next label
					int count = 0;  // current region size
					ls[j] = curlabel;

					// wavefront propagation
					while (ws >= wbuf) // wavefront not empty
					{
						count++;
						// put neighbors onto wavefront
						T* dpp = &img.at(p.y, p.x);
						T dp = *dpp;
						int* lpp = labels + width*p.y + p.x;

						if (p.y < height - 1 && !lpp[+width] && dpp[+dstep] != newVal && std::abs(dp - dpp[+dstep]) <= maxDiff)
						{
							lpp[+width] = curlabel;
							*ws++ = Point2s(p.x, p.y + 1);
						}

						if (p.y > 0 && !lpp[-width] && dpp[-dstep] != newVal && std::abs(dp - dpp[-dstep]) <= maxDiff)
						{
							lpp[-width] = curlabel;
							*ws++ = Point2s(p.x, p.y - 1);
						}

						if (p.x < width - 1 && !lpp[+1] && dpp[+1] != newVal && std::abs(dp - dpp[+1]) <= maxDiff)
						{
							lpp[+1] = curlabel;
							*ws++ = Point2s(p.x + 1, p.y);
						}

						if (p.x > 0 && !lpp[-1] && dpp[-1] != newVal && std::abs(dp - dpp[-1]) <= maxDiff)
						{
							lpp[-1] = curlabel;
							*ws++ = Point2s(p.x - 1, p.y);
						}

						// pop most recent and propagate
						// NB: could try least recent, maybe better convergence
						p = *--ws;
					}

					// assign label type
					if (count <= maxSpeckleSize)   // speckle region
					{
						rtype[ls[j]] = 1;   // small region label
						ds[j] = (T)newVal;
					}
					else
						rtype[ls[j]] = 0;   // large region label
				}
			}
		}
	}
}

좋은 웹페이지 즐겨찾기