PikaCV_Transforms.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. #include "PikaCV_Transforms.h"
  2. #include "PikaCV_Converter.h"
  3. #include "PikaCV_Filter.h"
  4. #include "PikaCV_common.h"
  5. #include "math.h"
  6. void PikaCV_Transforms_rotateDown(PikaObj* self, PikaObj* image) {
  7. PikaCV_Image* img = obj_getStruct(image, "image");
  8. if (NULL == img) {
  9. pika_assert(0);
  10. return;
  11. }
  12. if ((img->format != PikaCV_ImageFormat_Type_BGR888) &&
  13. (img->format != PikaCV_ImageFormat_Type_RGB888)) {
  14. obj_setErrorCode(self, PIKA_RES_ERR_OPERATION_FAILED);
  15. obj_setSysOut(self, "unsupported image format");
  16. return;
  17. }
  18. int width = img->width;
  19. int height = img->height;
  20. int size_new = width * height * 3;
  21. Arg* arg_data_new = arg_setBytes(NULL, "", NULL, size_new);
  22. uint8_t* data = _image_getData(image);
  23. uint8_t* data_new = arg_getBytes(arg_data_new);
  24. int i, j, k;
  25. /* rotate */
  26. for (i = 0; i < height; i++) {
  27. for (j = 0; j < width; j++) {
  28. for (k = 0; k < 3; k++) {
  29. data_new[(height - i - 1) * width * 3 + j * 3 + k] =
  30. data[i * width * 3 + j * 3 + k];
  31. }
  32. }
  33. }
  34. obj_setBytes(image, "_data", data_new, size_new);
  35. img->size = size_new;
  36. arg_deinit(arg_data_new);
  37. }
  38. void PikaCV_Transforms_threshold(PikaObj* self,
  39. PikaObj* image,
  40. int maxval,
  41. int thre,
  42. int thresholdType) {
  43. PikaCV_Image* src = obj_getStruct(image, "image");
  44. if (NULL == src) {
  45. pika_assert(0);
  46. return;
  47. }
  48. PikaCV_Format_Check(image, PikaCV_ImageFormat_Type_GRAY,
  49. PikaCV_Check_Converter);
  50. uint8_t* src_data = _image_getData(image);
  51. int i;
  52. if (thresholdType == 0) {
  53. for (i = 0; i < (src->size); i++) {
  54. src_data[i] = src_data[i] > thre ? maxval : 0;
  55. }
  56. } else if (thresholdType == 1) {
  57. for (i = 0; i < (src->size); i++) {
  58. src_data[i] = src_data[i] > thre ? 0 : maxval;
  59. }
  60. } else if (thresholdType == 2) {
  61. for (i = 0; i < (src->size); i++) {
  62. src_data[i] = src_data[i] > thre ? thre : src_data[i];
  63. }
  64. } else if (thresholdType == 3) {
  65. for (i = 0; i < (src->size); i++) {
  66. src_data[i] = src_data[i] > thre ? src_data[i] : 0;
  67. }
  68. } else if (thresholdType == 4) {
  69. for (i = 0; i < (src->size); i++) {
  70. src_data[i] = src_data[i] > thre ? 0 : src_data[i];
  71. }
  72. } else if (thresholdType == 5) {
  73. PikaCV_Transforms_setOTSU(self, image);
  74. } else {
  75. pika_assert(0);
  76. return;
  77. }
  78. obj_setBytes(image, "_data", src_data, src->size);
  79. }
  80. void PikaCV_Transforms_setROI(PikaObj* self,
  81. PikaObj* image,
  82. int x,
  83. int y,
  84. int w,
  85. int h) {
  86. PikaCV_Image* src = obj_getStruct(image, "image");
  87. int width = src->width;
  88. int height = src->height;
  89. if (NULL == src) {
  90. pika_assert(0);
  91. return;
  92. }
  93. PikaCV_Format_Check(image, PikaCV_ImageFormat_Type_RGB888,
  94. PikaCV_Check_Converter);
  95. if (x <= 0 || y <= 0 || w <= 0 || h <= 0) {
  96. pika_assert(0);
  97. return;
  98. }
  99. if (x + w > width || y + h > height) {
  100. pika_assert(0);
  101. return;
  102. }
  103. int size_new = h * w * 3;
  104. Arg* arg_data_new = arg_setBytes(NULL, "", NULL, size_new);
  105. uint8_t* data = _image_getData(image);
  106. uint8_t* data_new = arg_getBytes(arg_data_new);
  107. for (int i = 0; i < h; i++) {
  108. for (int j = 0; j < w; j++) {
  109. data_new[i * 3 * w + j * 3] =
  110. data[(i + y - 1) * width * 3 + (j + x - 1) * 3];
  111. data_new[i * 3 * w + j * 3 + 1] =
  112. data[(i + y - 1) * width * 3 + (j + x - 1) * 3 + 1];
  113. data_new[i * 3 * w + j * 3 + 2] =
  114. data[(i + y - 1) * width * 3 + (j + x - 1) * 3 + 2];
  115. }
  116. }
  117. src->height = h;
  118. src->width = w;
  119. src->size = size_new;
  120. obj_setBytes(image, "_data", data_new, size_new);
  121. arg_deinit(arg_data_new);
  122. }
  123. int PikaCV_Transforms_getOTSUthre(PikaObj* self, PikaObj* image) {
  124. PikaCV_Image* src = obj_getStruct(image, "image");
  125. if (NULL == src) {
  126. pika_assert(0);
  127. return 0;
  128. }
  129. PikaCV_Format_Check(image, PikaCV_ImageFormat_Type_GRAY,
  130. PikaCV_Check_Converter);
  131. const int Grayscale = 256;
  132. int width = src->width;
  133. int height = src->height;
  134. int size = src->size;
  135. int threshold = 0;
  136. int graynum[256] = {0};
  137. uint8_t* data = _image_getData(image);
  138. for (int i = 0; i < size; i++) {
  139. graynum[data[i]]++;
  140. }
  141. pika_float P[256] = {0.0};
  142. pika_float PK[256] = {0.0};
  143. pika_float MK[256] = {0.0};
  144. pika_float srcpixnum = width * height, sumtmpPK = 0, sumtmpMK = 0;
  145. for (int i = 0; i < Grayscale; ++i) {
  146. P[i] = graynum[i] / srcpixnum;
  147. PK[i] = sumtmpPK + P[i];
  148. sumtmpPK = PK[i];
  149. MK[i] = sumtmpMK + i * P[i];
  150. sumtmpMK = MK[i];
  151. }
  152. pika_float Var = 0;
  153. for (int k = 0; k < Grayscale; ++k) {
  154. if (PK[k] > 0.0) {
  155. pika_float t = MK[Grayscale - 1] * PK[k] - MK[k];
  156. pika_float w = PK[k] * (1 - PK[k]);
  157. pika_float variance = t * t / w;
  158. if (variance > Var) {
  159. Var = variance;
  160. threshold = k;
  161. }
  162. }
  163. }
  164. return threshold;
  165. }
  166. void PikaCV_Transforms_setOTSU(PikaObj* self, PikaObj* image) {
  167. PikaCV_Image* src = obj_getStruct(image, "image");
  168. if (NULL == src) {
  169. pika_assert(0);
  170. return;
  171. }
  172. PikaCV_Format_Check(image, PikaCV_ImageFormat_Type_GRAY,
  173. PikaCV_Check_Converter);
  174. int thre = PikaCV_Transforms_getOTSUthre(self, image);
  175. uint8_t* src_data = _image_getData(image);
  176. int i;
  177. for (i = 0; i < (src->size); i++) {
  178. src_data[i] = src_data[i] > thre ? 255 : 0;
  179. }
  180. obj_setBytes(image, "_data", src_data, src->size);
  181. }
  182. #define MAX(a, b) ((a) > (b) ? (a) : (b))
  183. #define MIN(a, b) ((a) < (b) ? (a) : (b))
  184. void PikaCV_Transforms_resize(PikaObj* self,
  185. PikaObj* image,
  186. int x,
  187. int y,
  188. int resizeType) {
  189. PikaCV_Image* src = obj_getStruct(image, "image");
  190. int width = src->width;
  191. int height = src->height;
  192. if (NULL == src) {
  193. pika_assert(0);
  194. return;
  195. }
  196. if (x <= 0 || y <= 0) {
  197. pika_assert(0);
  198. return;
  199. }
  200. PikaCV_Format_Check(image, PikaCV_ImageFormat_Type_RGB888,
  201. PikaCV_Check_Converter);
  202. int size_new = x * y * 3;
  203. Arg* arg_data_new = arg_setBytes(NULL, "", NULL, size_new);
  204. uint8_t* data = _image_getData(image);
  205. uint8_t* data_new = arg_getBytes(arg_data_new);
  206. pika_float scale_x = (pika_float)width / (pika_float)x;
  207. pika_float scale_y = (pika_float)height / (pika_float)y;
  208. if (resizeType == 0) {
  209. for (int i = 0; i < y; ++i) {
  210. int sy = floor(i * scale_y);
  211. sy = MIN(sy, (height - 1));
  212. for (int j = 0; j < x; ++j) {
  213. int sx = floor(j * scale_x);
  214. sx = MIN(sx, (width - 1));
  215. data_new[i * x * 3 + j * 3] = data[sy * width * 3 + sx * 3];
  216. data_new[i * x * 3 + j * 3 + 1] =
  217. data[sy * width * 3 + sx * 3 + 1];
  218. data_new[i * x * 3 + j * 3 + 2] =
  219. data[sy * width * 3 + sx * 3 + 2];
  220. }
  221. }
  222. } else {
  223. pika_assert(0);
  224. return;
  225. }
  226. src->height = y;
  227. src->width = x;
  228. src->size = size_new;
  229. obj_setBytes(image, "_data", data_new, size_new);
  230. arg_deinit(arg_data_new);
  231. }
  232. void PikaCV_Transforms_adaptiveThreshold(PikaObj* self,
  233. PikaObj* image,
  234. int maxval,
  235. int subsize,
  236. int c,
  237. int method) {
  238. PikaCV_Image* src = obj_getStruct(image, "image");
  239. if (NULL == src) {
  240. pika_assert(0);
  241. return;
  242. }
  243. if (c < 0 || c > 255) {
  244. pika_assert(0);
  245. return;
  246. }
  247. PikaCV_Format_Check(image, PikaCV_ImageFormat_Type_GRAY,
  248. PikaCV_Check_Converter);
  249. int size = src->size;
  250. uint8_t* src_data = _image_getData(image);
  251. uint8_t* src_copy;
  252. src_copy = (uint8_t*)calloc(size, 1);
  253. memcpy(src_copy, src_data, size);
  254. if (method == 0) {
  255. PikaCV_Filter_meanFilter(self, image, subsize, subsize);
  256. } else if (method == 1) {
  257. PikaCV_Filter_medianFilter(self, image);
  258. } else {
  259. free(src_copy);
  260. return;
  261. }
  262. /* update size after filter */
  263. size = src->size;
  264. uint8_t* smooth_data = _image_getData(image);
  265. for (int i = 0; i < size; i++) {
  266. uint8_t result = smooth_data[i] - (uint8_t)c;
  267. smooth_data[i] =
  268. ((result < MIN(smooth_data[i], (uint8_t)c)) ? 0 : result);
  269. }
  270. for (int i = 0; i < size; i++) {
  271. src_copy[i] = ((src_copy[i] > smooth_data[i]) ? (uint8_t)maxval : 0);
  272. }
  273. obj_setBytes(image, "_data", src_copy, size);
  274. free(src_copy);
  275. }
  276. #undef MAX
  277. #undef MIN