CAlignAndCutImage.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. #include "defines.h"
  2. #include "CAlignAndCutImage.h"
  3. #include "ClassFlowAlignment.h"
  4. #include "ClassControllCamera.h"
  5. #include "CRotateImage.h"
  6. #include "ClassLogFile.h"
  7. #include <math.h>
  8. #include <algorithm>
  9. #include <esp_log.h>
  10. #include "psram.h"
  11. static const char *TAG = "c_align_and_cut_image";
  12. CAlignAndCutImage::CAlignAndCutImage(std::string _name, CImageBasis *_org, CImageBasis *_temp) : CImageBasis(_name)
  13. {
  14. name = _name;
  15. rgb_image = _org->rgb_image;
  16. channels = _org->channels;
  17. width = _org->width;
  18. height = _org->height;
  19. bpp = _org->bpp;
  20. externalImage = true;
  21. islocked = false;
  22. ImageTMP = _temp;
  23. }
  24. void CAlignAndCutImage::GetRefSize(int *ref_dx, int *ref_dy)
  25. {
  26. ref_dx[0] = t0_dx;
  27. ref_dy[0] = t0_dy;
  28. ref_dx[1] = t1_dx;
  29. ref_dy[1] = t1_dy;
  30. }
  31. int CAlignAndCutImage::Align(RefInfo *_temp1, RefInfo *_temp2)
  32. {
  33. CFindTemplate *ft = new CFindTemplate("align", rgb_image, channels, width, height, bpp);
  34. //////////////////////////////////////////////
  35. bool isSimilar1 = ft->FindTemplate(_temp1); // search the alignment image 1
  36. _temp1->width = ft->tpl_width;
  37. _temp1->height = ft->tpl_height;
  38. int x1_relative_shift = (_temp1->target_x - _temp1->found_x);
  39. int y1_relative_shift = (_temp1->target_y - _temp1->found_y);
  40. int x1_absolute_shift = _temp1->target_x + (_temp1->target_x - _temp1->found_x);
  41. int y1_absolute_shift = _temp1->target_y + (_temp1->target_y - _temp1->found_y);
  42. //////////////////////////////////////////////
  43. bool isSimilar2 = ft->FindTemplate(_temp2); // search the alignment image 2
  44. _temp2->width = ft->tpl_width;
  45. _temp2->height = ft->tpl_height;
  46. int x2_relative_shift = (_temp2->target_x - _temp2->found_x);
  47. int y2_relative_shift = (_temp2->target_y - _temp2->found_y);
  48. int x2_absolute_shift = _temp2->target_x + (_temp2->target_x - _temp2->found_x);
  49. int y2_absolute_shift = _temp2->target_y + (_temp2->target_y - _temp2->found_y);
  50. delete ft;
  51. int ret = Alignment_OK;
  52. //////////////////////////////////////////////
  53. float radians_org = atan2((_temp2->found_y - _temp1->found_y), (_temp2->found_x - _temp1->found_x));
  54. float radians_cur = atan2((y2_absolute_shift - y1_absolute_shift), (x2_absolute_shift - x1_absolute_shift));
  55. float rotate_angle = (radians_cur - radians_org) * 180 / M_PI; // radians to degrees
  56. //////////////////////////////////////////////
  57. if ((fabs(rotate_angle) > _temp1->search_max_angle) || (fabs(rotate_angle) > _temp2->search_max_angle))
  58. {
  59. ret = Rotation_Alignment_Failed;
  60. }
  61. if ((abs(x1_relative_shift) >= _temp1->search_x) || (abs(y1_relative_shift) >= _temp1->search_y))
  62. {
  63. ret = Shift_Alignment_Failed;
  64. }
  65. //////////////////////////////////////////////
  66. CRotateImage rt("Align", this, ImageTMP);
  67. if (rotate_angle != 0)
  68. {
  69. rt.Translate(x1_relative_shift, y1_relative_shift);
  70. if (Camera.ImageAntialiasing)
  71. {
  72. rt.RotateAntiAliasing(rotate_angle, _temp1->target_x, _temp1->target_y);
  73. }
  74. else
  75. {
  76. rt.Rotate(rotate_angle, _temp1->target_x, _temp1->target_y);
  77. }
  78. }
  79. else if (x1_relative_shift != 0 || y1_relative_shift != 0)
  80. {
  81. rt.Translate(x1_relative_shift, y1_relative_shift);
  82. }
  83. return ((isSimilar1 && isSimilar2) ? Fast_Alignment_OK : ret);
  84. }
  85. void CAlignAndCutImage::CutAndSave(std::string _template1, int x1, int y1, int dx, int dy)
  86. {
  87. int x2 = std::min((x1 + dx), (width - 1));
  88. int y2 = std::min((y1 + dy), (height - 1));
  89. dx = x2 - x1;
  90. dy = y2 - y1;
  91. int memsize = dx * dy * channels;
  92. uint8_t *temp_image = (unsigned char *)malloc_psram_heap(std::string(TAG) + "->temp_image", memsize, MALLOC_CAP_SPIRAM);
  93. stbi_uc *p_target;
  94. stbi_uc *p_source;
  95. RGBImageLock();
  96. for (int x = x1; x < x2; ++x)
  97. {
  98. for (int y = y1; y < y2; ++y)
  99. {
  100. p_target = temp_image + (channels * ((y - y1) * dx + (x - x1)));
  101. p_source = rgb_image + (channels * (y * width + x));
  102. for (int _channels = 0; _channels < channels; ++_channels)
  103. {
  104. p_target[_channels] = p_source[_channels];
  105. }
  106. }
  107. }
  108. #ifdef STBI_ONLY_JPEG
  109. stbi_write_jpg(_template1.c_str(), dx, dy, channels, temp_image, 100);
  110. #else
  111. stbi_write_bmp(_template1.c_str(), dx, dy, channels, temp_image);
  112. #endif
  113. RGBImageRelease();
  114. stbi_image_free(temp_image);
  115. }
  116. void CAlignAndCutImage::CutAndSave(int x1, int y1, int dx, int dy, CImageBasis *_target)
  117. {
  118. int x2 = std::min((x1 + dx), (width - 1));
  119. int y2 = std::min((y1 + dy), (height - 1));
  120. dx = x2 - x1;
  121. dy = y2 - y1;
  122. if ((_target->height != dy) || (_target->width != dx) || (_target->channels != channels))
  123. {
  124. ESP_LOGD(TAG, "CAlignAndCutImage::CutAndSave - Image size does not match!");
  125. return;
  126. }
  127. uint8_t *temp_image = _target->RGBImageLock();
  128. RGBImageLock();
  129. stbi_uc *p_target;
  130. stbi_uc *p_source;
  131. for (int x = x1; x < x2; ++x)
  132. {
  133. for (int y = y1; y < y2; ++y)
  134. {
  135. p_target = temp_image + (channels * ((y - y1) * dx + (x - x1)));
  136. p_source = rgb_image + (channels * (y * width + x));
  137. for (int _channels = 0; _channels < channels; ++_channels)
  138. {
  139. p_target[_channels] = p_source[_channels];
  140. }
  141. }
  142. }
  143. RGBImageRelease();
  144. _target->RGBImageRelease();
  145. }
  146. CImageBasis *CAlignAndCutImage::CutAndSave(int x1, int y1, int dx, int dy)
  147. {
  148. int x2 = std::min((x1 + dx), (width - 1));
  149. int y2 = std::min((y1 + dy), (height - 1));
  150. dx = x2 - x1;
  151. dy = y2 - y1;
  152. int memsize = dx * dy * channels;
  153. uint8_t *temp_image = (unsigned char *)malloc_psram_heap(std::string(TAG) + "->temp_image", memsize, MALLOC_CAP_SPIRAM);
  154. stbi_uc *p_target;
  155. stbi_uc *p_source;
  156. RGBImageLock();
  157. for (int x = x1; x < x2; ++x)
  158. {
  159. for (int y = y1; y < y2; ++y)
  160. {
  161. p_target = temp_image + (channels * ((y - y1) * dx + (x - x1)));
  162. p_source = rgb_image + (channels * (y * width + x));
  163. for (int _channels = 0; _channels < channels; ++_channels)
  164. {
  165. p_target[_channels] = p_source[_channels];
  166. }
  167. }
  168. }
  169. CImageBasis *rs = new CImageBasis("CutAndSave", temp_image, channels, dx, dy, bpp);
  170. RGBImageRelease();
  171. rs->SetIndepended();
  172. return rs;
  173. }