30 vote_reserve_size_(10),
44 d_theta_ =
static_cast<float>(M_PI) * d_theta / 180.0f;
45 r_size_ =
static_cast<int>(
46 2 * sqrtf(
static_cast<float>(img_w_ * img_w_ + img_h_ * img_h_)) / d_r_);
47 theta_size_ =
static_cast<int>(M_PI / d_theta_);
51 vote_map_.resize(r_size_ * theta_size_, 0);
53 query_map_.resize(img_w_ * img_h_);
54 for (
auto& query : query_map_) {
55 query.resize(theta_size_, 0);
58 for (
int theta_idx = 0; theta_idx < theta_size_; ++theta_idx) {
59 float cur_theta = d_theta_ *
static_cast<float>(theta_idx);
60 for (
int img_pos = 0; img_pos < img_w_ * img_h_; ++img_pos) {
61 int w = img_pos % img_w_;
62 int h = img_pos / img_w_;
64 static_cast<int>((cos(cur_theta) * w + sin(cur_theta) * h) / d_r_) +
66 if (0 <= r && r < r_size_) {
67 query_map_[img_pos][theta_idx] = r * theta_size_ + theta_idx;
72 distribute_map_.resize(r_size_ * theta_size_);
73 for (
auto& distribute : distribute_map_) {
74 distribute.reserve(vote_reserve_size_);
77 if (CheckPrepared()) {
92 bool with_distribute) {
93 if (image.size() != query_map_.size()) {
97 for (
size_t i = 0; i < image.size(); ++i) {
99 int x =
static_cast<int>(i) % img_w_;
100 int y =
static_cast<int>(i) / img_w_;
112 const int pos = y * img_w_ + x;
118 for (
int theta_idx = 0; theta_idx < theta_size_; ++theta_idx) {
119 ++vote_map_[query_map_[pos][theta_idx]];
120 if (with_distribute) {
121 distribute_map_[query_map_[pos][theta_idx]].push_back(pos);
134 bool with_distribute,
135 std::vector<HoughLine>* lines)
const {
139 int r_step = 2 * r_neibor + 1;
140 int theta_step = 2 * theta_neibor + 1;
143 std::set<int> max_vote_lines;
144 GetMaxVotes(min_pt_num, r_neibor, theta_neibor, r_step, theta_step,
148 lines->resize(max_vote_lines.size());
150 for (
auto i = max_vote_lines.begin(); i != max_vote_lines.end(); ++i) {
151 if (!VotePosToHoughLine(*i, with_distribute, &(*lines)[idx++])) {
159 unsigned int size = 0;
162 static_cast<unsigned int>(vote_map_.capacity() *
sizeof(vote_map_[0]));
163 size +=
static_cast<unsigned int>(query_map_.capacity() *
164 sizeof(query_map_[0]));
165 size +=
static_cast<unsigned int>(theta_size_ * query_map_.size() *
166 sizeof(query_map_[0][0]));
167 size +=
static_cast<unsigned int>(distribute_map_.capacity() *
168 sizeof(distribute_map_[0]));
169 for (
const auto& distribute : distribute_map_) {
170 size +=
static_cast<unsigned int>(distribute.capacity() *
171 sizeof(distribute[0]));
181 for (
auto& distribute : distribute_map_) {
182 distribute.shrink_to_fit();
187 memset(vote_map_.data(), 0, vote_map_.size() *
sizeof(vote_map_[0]));
188 if (with_distribute) {
189 for (
auto& distribute : distribute_map_) {
197 vote_map_.shrink_to_fit();
199 query_map_.shrink_to_fit();
200 distribute_map_.clear();
201 distribute_map_.shrink_to_fit();
205bool HoughTransfer::CheckPrepared()
const {
206 if (
static_cast<int>(vote_map_.size()) != r_size_ * theta_size_) {
209 if (
static_cast<int>(query_map_.size()) != img_w_ * img_h_) {
212 if (
static_cast<int>(distribute_map_.size()) != r_size_ * theta_size_) {
215 if (vote_map_.empty() || query_map_.empty() || distribute_map_.empty()) {
221void HoughTransfer::GetMaxVotes(
int min_pt_num,
int r_neibor,
int theta_neibor,
222 int r_step,
int theta_step,
223 std::set<int>* max_vote_lines)
const {
224 for (
int i = r_neibor; i < r_size_ - r_neibor; i += r_step) {
225 for (
int j = theta_neibor; j < theta_size_ - theta_neibor;
228 int max_vote = min_pt_num;
229 for (
int m = -r_neibor; m <= r_neibor; ++m) {
230 for (
int n = -theta_neibor; n <= theta_neibor; ++n) {
231 int neibor_pos = (i + m) * theta_size_ + j + n;
232 if (vote_map_[neibor_pos] >= max_vote) {
233 max_pos = neibor_pos;
234 max_vote = vote_map_[neibor_pos];
239 max_vote_lines->insert(max_pos);
245bool HoughTransfer::VotePosToHoughLine(
int vote_pos,
bool with_distribute,
246 HoughLine* out_line)
const {
250 out_line->r =
static_cast<float>(vote_pos / theta_size_ - r_size_ / 2) * d_r_;
251 out_line->theta =
static_cast<float>(vote_pos % theta_size_) * d_theta_;
252 out_line->vote_num = vote_map_[vote_pos];
253 if (with_distribute) {
254 if (out_line->vote_num !=
255 static_cast<int>(distribute_map_[vote_pos].size())) {
258 out_line->pts = distribute_map_[vote_pos];
259 const int start_pos = distribute_map_[vote_pos][0];
260 const int end_pos = distribute_map_[vote_pos][out_line->vote_num - 1];
261 const int start_x = start_pos % img_w_;
262 const int start_y = start_pos / img_w_;
263 const int end_x = end_pos % img_w_;
264 const int end_y = end_pos / img_w_;
266 sqrtf(
static_cast<float>((start_x - end_x) * (start_x - end_x) +
267 (start_y - end_y) * (start_y - end_y)));
bool ImageVote(const std::vector< int > &image, bool with_distribute)
unsigned int MemoryConsume() const
bool Init(int img_w, int img_h, float d_r, float d_theta)
void ResetMaps(bool with_distribute)
bool GetLines(int min_pt_num, int r_neibor, int theta_neibor, bool with_distribute, std::vector< HoughLine > *lines) const
void PointVote(int x, int y, bool with_distribute)