File: BlockMotionSearch.cpp

package info (click to toggle)
uprightdiff 1.4.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, sid
  • size: 144 kB
  • sloc: cpp: 893; makefile: 11
file content (83 lines) | stat: -rw-r--r-- 2,487 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <cstring>

#include "BlockMotionSearch.h"
#include "OutwardAlternatingSearch.h"

BlockMotionSearch::Mat1i BlockMotionSearch::search() {
	int yBlockCount = m_source.rows / m_blockSize;
	int xBlockCount = m_source.cols / m_blockSize;
	m_blockMotion = Mat1i(yBlockCount, xBlockCount);

	for (m_yIndex = 0; m_yIndex < yBlockCount; m_yIndex++) {
		m_y = m_yIndex * m_blockSize;
		for (m_xIndex = 0; m_xIndex < xBlockCount; m_xIndex++) {
			m_x = m_xIndex * m_blockSize;
			cv::Rect sourceRect(m_x, m_y, m_blockSize, m_blockSize);
			Mat3b sourceBlock = m_source(sourceRect);

			// Priority 1: exactly constant baseline
			if (m_xIndex > 0 && m_blockMotion(m_yIndex, m_xIndex - 1) != NOT_FOUND) {
				if (tryMotion(sourceBlock, m_blockMotion(m_yIndex, m_xIndex - 1))) {
					continue;
				}
			}

			int searchStart;
			if (m_yIndex > 0 && m_blockMotion(m_yIndex - 1, m_xIndex) != NOT_FOUND) {
				// Priority 2: near-constant vertical flow
				searchStart = m_y + m_blockMotion(m_yIndex - 1, m_xIndex);
			} else if (m_xIndex > 0 && m_blockMotion(m_yIndex, m_xIndex - 1) != NOT_FOUND) {
				// Priority 3: near-constant baseline
				searchStart = m_y + m_blockMotion(m_yIndex, m_xIndex - 1);
			} else {
				// Priority 4: source offset
				searchStart = m_y;
			}
			// Check bounds of searchStart
			if (searchStart > m_dest.rows - m_blockSize) {
				searchStart = m_dest.rows - m_blockSize;
			}
			if (searchStart < 0) {
				searchStart = 0;
			}

			// Make sure the search window includes the no-change case
			int tempWindowSize = std::max(std::abs(searchStart - m_y), m_windowSize);

			OutwardAlternatingSearch search(searchStart, m_dest.rows - m_blockSize + 1,
					tempWindowSize);
			m_blockMotion(m_yIndex, m_xIndex) = NOT_FOUND;
			for (; search; ++search) {
				if (tryMotion(sourceBlock, search.pos() - m_y)) {
					break;
				}
			}
		}
	}
	return m_blockMotion;
}

bool BlockMotionSearch::tryMotion(const Mat3b & sourceBlock, int dy) {
	cv::Rect destRect(m_x, m_y + dy, m_blockSize, m_blockSize);
	Mat3b destBlock = m_dest(destRect);
	if (blockEqual(sourceBlock, destBlock)) {
		m_blockMotion(m_yIndex, m_xIndex) = dy;
		return true;
	} else {
		return false;
	}
}

bool BlockMotionSearch::blockEqual(const Mat3b & m1, const Mat3b & m2) {
	if (m1.size() != m2.size()) {
		return false;
	}
	int rowSize = m1.cols * m1.elemSize();
	for (int y = 0; y < m1.rows; y++) {
		if (std::memcmp(m1.ptr(y), m2.ptr(y), rowSize) != 0) {
			return false;
		}
	}
	return true;
}