OSCR

Behavioral techniques for controlling visual stimuli to modulate visual processing in the brain and their implementation in augmented reality technology

Code ↔ Paper

The paper beside its authors' code: matches between them have not been computed for this paper yet.

Paper

Loaded from Europe PMC by your browser; OSCR does not store it: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

Java · 537 lines · 24 KB · no license

  1. package com.example.opencv_test10;
  2. import androidx.annotation.NonNull;
  3. //import androidx.appcompat.app.AppCompatActivity;
  4. //import android.app.ActionBar;
  5. import android.media.AudioManager;
  6. import android.media.ToneGenerator;
  7. import android.os.Bundle;
  8. import android.os.Environment;
  9. import android.util.Log;
  10. //import android.view.ActionMode;
  11. import android.view.GestureDetector;
  12. import android.view.MotionEvent;
  13. import android.view.ScaleGestureDetector;
  14. //import android.view.ScaleGestureDetector.SimpleOnScaleGestureListener;
  15. import android.view.SurfaceView;
  16. import android.view.View;
  17. import android.view.Window;
  18. //import android.view.WindowManager;
  19. import org.opencv.android.BaseLoaderCallback;
  20. import org.opencv.android.CameraActivity;
  21. import org.opencv.android.CameraBridgeViewBase;
  22. import org.opencv.android.LoaderCallbackInterface;
  23. import org.opencv.android.OpenCVLoader;
  24. import org.opencv.core.Core;
  25. import org.opencv.core.CvType;
  26. import org.opencv.core.Mat;
  27. import org.opencv.core.Rect;
  28. import org.opencv.core.Scalar;
  29. import org.opencv.core.Size;
  30. //import org.opencv.core.Scalar;
  31. import org.opencv.imgcodecs.Imgcodecs;
  32. import org.opencv.imgproc.Imgproc;
  33. import java.io.File;
  34. import java.text.SimpleDateFormat;
  35. import java.util.ArrayList;
  36. import java.util.Arrays;
  37. import java.util.Collections;
  38. import java.util.Date;
  39. import java.util.List;
  40. import static java.lang.Math.abs;
  41. import static org.opencv.android.CameraRenderer.LOGTAG;
  42. import static org.opencv.core.Core.BORDER_DEFAULT;
  43. import static org.opencv.imgproc.Imgproc.THRESH_TOZERO;
  44. public class MainActivity extends CameraActivity {
  45. Mat img_zero, img_filtered, img_stereo;
  46. Mat img_rgba, img_gray, img_invgray, img_isolumR, img_isolumG;
  47. Mat img_sobel01, img_sobel10, img_temp8UC;
  48. Mat img_noise, img_gray32F;
  49. boolean used_rgba, used_invgray, used_isolumRG; // used_gray, used_sobels
  50. ArrayList<Mat> channels_rgba;
  51. Mat mat_lut_Red, mat_lut_Green;
  52. Rect half_rect, srcL_rect, srcR_rect, dstL_rect, dstR_rect;
  53. int cam_width,cam_height, cam_half_width, cam_quarter_width;
  54. int capture = 0;
  55. int imgtype = 1;
  56. int separation = 100;
  57. private static String LOGTAG = "OpenCV_Log";
  58. private CameraBridgeViewBase mOpenCvCameraView;
  59. private GestureDetector gestureDetector;
  60. private ScaleGestureDetector scaleGestureDetector;
  61. private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
  62. @Override
  63. public void onManagerConnected(int status) {
  64. switch (status){
  65. case LoaderCallbackInterface.SUCCESS:{
  66. Log.v(LOGTAG,"OpenCV Loaded");
  67. mOpenCvCameraView.enableView();
  68. } break;
  69. default:
  70. {
  71. super.onManagerConnected(status);
  72. } break;
  73. }
  74. super.onManagerConnected(status);
  75. }
  76. };
  77. @Override
  78. protected void onCreate(Bundle savedInstanceState) {
  79. super.onCreate(savedInstanceState);
  80. requestWindowFeature(Window.FEATURE_NO_TITLE);
  81. setContentView(R.layout.activity_main);
  82. final android.view.WindowInsetsController insetsController = getWindow().getInsetsController();
  83. if (insetsController != null) {
  84. insetsController.hide(android.view.WindowInsets.Type.statusBars());
  85. insetsController.setSystemBarsBehavior(android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
  86. }
  87. mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.opencv_surface_view);
  88. mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
  89. mOpenCvCameraView.setCvCameraViewListener(cvCameraViewListener);
  90. gestureDetector = new GestureDetector(this, new GestureListener());
  91. scaleGestureDetector = new ScaleGestureDetector(this, new PinchZoomListener());
  92. mOpenCvCameraView.setOnTouchListener(new View.OnTouchListener() {
  93. @Override
  94. public boolean onTouch(View v, MotionEvent event) {
  95. gestureDetector.onTouchEvent(event);
  96. scaleGestureDetector.onTouchEvent(event);
  97. return true;
  98. }
  99. });
  100. }
  101. private class GestureListener extends GestureDetector.SimpleOnGestureListener {
  102. @Override
  103. public boolean onSingleTapUp(MotionEvent e) {
  104. capture = 1;
  105. return true;
  106. }
  107. @Override
  108. public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
  109. int pretype = imgtype;
  110. float swipeX = e1.getX() - e2.getX();
  111. float swipeY = e1.getY() - e2.getY();
  112. if (swipeY > 50 && abs(swipeY) > abs(swipeX)) { // Upward
  113. imgtype++;
  114. if(imgtype > 12) imgtype = 0;
  115. }
  116. else if (swipeY < -50 && abs(swipeY) > abs(swipeX)) { // Downward
  117. imgtype--;
  118. if(imgtype < 0) imgtype = 12;
  119. }
  120. if(imgtype==pretype)
  121. return false;
  122. boolean pre_used_rgba=used_rgba, pre_used_invgray=used_invgray; //pre_used_gray=used_gray,
  123. boolean pre_used_isolumRG=used_isolumRG; //pre_used_sobels=used_sobels
  124. used_rgba=false; used_invgray=false; used_isolumRG=false; //used_gray=false; used_sobels=false;
  125. switch(imgtype) {
  126. case 0: // RGB
  127. used_rgba = true;
  128. break;
  129. case 1: // Gray
  130. //used_gray = true;
  131. break;
  132. case 2: // Red Only
  133. //used_gray = true;
  134. used_isolumRG = true;
  135. break;
  136. case 3: // Red-inv Only
  137. //used_gray = true;
  138. used_invgray = true; used_isolumRG = true;
  139. break;
  140. case 4: // Green Only
  141. //used_gray = true;
  142. used_invgray = true; used_isolumRG = true;
  143. break;
  144. case 5: // Green-inv Only
  145. //used_gray = true;
  146. used_isolumRG = true;
  147. break;
  148. case 6: // Red-Green
  149. //used_gray = true;
  150. used_isolumRG = true;
  151. break;
  152. case 7: // Green-Red
  153. //used_gray = true;
  154. used_isolumRG = true; used_invgray = true;
  155. break;
  156. case 8: // Contour
  157. //used_gray = true; used_sobels = true;
  158. break;
  159. case 11: // 2nd-order-inv
  160. used_invgray = true;
  161. break;
  162. case 12: // Gray-inv
  163. used_invgray = true;
  164. break;
  165. default: // 7~9, Default == Gray
  166. //used_gray = true;
  167. break;
  168. }
  169. if(pre_used_rgba==false && used_rgba==true) {
  170. img_rgba = new Mat(cam_height, cam_width, CvType.CV_8UC4);
  171. channels_rgba = new ArrayList<>(4);
  172. }
  173. //if(pre_used_gray==false && used_gray==true) img_gray = new Mat(cam_height, cam_width, CvType.CV_8U);
  174. if(pre_used_invgray==false && used_invgray==true) img_invgray = new Mat(cam_height, cam_width, CvType.CV_8U);
  175. if(pre_used_isolumRG==false && used_isolumRG==true) {
  176. img_isolumR = new Mat(cam_height, cam_width, CvType.CV_8U);
  177. img_isolumG = new Mat(cam_height, cam_width, CvType.CV_8U);
  178. }
  179. //if(pre_used_sobels==false && used_sobels==true) {
  180. // img_sobel01 = new Mat(cam_height, cam_width, CvType.CV_16S);
  181. // img_sobel10 = new Mat(cam_height, cam_width, CvType.CV_16S);
  182. // img_temp8UC = new Mat(cam_height, cam_width, CvType.CV_8U);
  183. //}
  184. if(pre_used_rgba==true && used_rgba==false) {
  185. img_rgba.release();
  186. channels_rgba.get(0).release();
  187. channels_rgba.get(1).release();
  188. channels_rgba.get(2).release();
  189. channels_rgba.get(3).release();
  190. }
  191. //if(pre_used_gray==true && used_gray==false) img_gray.release();
  192. if(pre_used_invgray==true && used_invgray==false)
  193. img_invgray.release();
  194. if(pre_used_isolumRG==true && used_isolumRG==false) {
  195. img_isolumR.release();
  196. img_isolumG.release();
  197. }
  198. //if(pre_used_sobels==true && used_sobels==false) {
  199. // img_sobel01.release();
  200. // img_sobel10.release();
  201. // img_temp8UC.release();
  202. //}
  203. return true;
  204. }
  205. }
  206. public class PinchZoomListener extends ScaleGestureDetector.SimpleOnScaleGestureListener{
  207. @Override
  208. public boolean onScale(@NonNull ScaleGestureDetector detector) {
  209. //float temp_scale = detector.getScaleFactor();
  210. float temp_span1 = detector.getCurrentSpan();
  211. float temp_span0 = detector.getPreviousSpan();
  212. float temp_val = temp_span1 - temp_span0;
  213. separation += temp_val;
  214. if(separation<0) separation=0;
  215. if(separation>cam_half_width) separation=cam_half_width;
  216. Log.d("ScaleGestureDetector", "Separation: " + separation);
  217. return true;
  218. }
  219. }
  220. @Override
  221. protected List<?extends CameraBridgeViewBase> getCameraViewList() {
  222. return Collections.singletonList(mOpenCvCameraView);
  223. }
  224. private CameraBridgeViewBase.CvCameraViewListener2 cvCameraViewListener = new CameraBridgeViewBase.CvCameraViewListener2() {
  225. private int lut_Red_int[] = {
  226. 27, 27, 44, 44, 56, 56, 66, 66, 74, 74, 81, 81, 88, 88, 94, 94,
  227. 100, 100, 100, 105, 105, 105, 110, 110, 110, 114, 114, 114, 119, 119, 119, 123,
  228. 123, 123, 127, 127, 127, 131, 131, 131, 134, 134, 134, 138, 138, 138, 141, 141,
  229. 141, 145, 145, 145, 148, 148, 148, 151, 151, 151, 154, 154, 154, 157, 157, 157,
  230. 159, 159, 159, 162, 162, 162, 165, 165, 165, 167, 167, 167, 170, 170, 170, 172,
  231. 172, 172, 175, 175, 175, 177, 177, 177, 179, 179, 179, 181, 181, 181, 183, 183,
  232. 183, 186, 186, 186, 188, 188, 188, 190, 190, 190, 192, 192, 192, 193, 193, 193,
  233. 195, 195, 195, 197, 197, 197, 199, 199, 199, 201, 201, 201, 202, 202, 202, 204,
  234. 204, 204, 206, 206, 206, 207, 207, 207, 209, 209, 209, 210, 210, 210, 212, 212,
  235. 212, 213, 213, 213, 215, 215, 215, 216, 216, 216, 217, 217, 217, 219, 219, 219,
  236. 220, 220, 220, 221, 221, 221, 222, 222, 222, 224, 224, 224, 225, 225, 225, 226,
  237. 226, 226, 227, 227, 227, 228, 228, 228, 229, 229, 229, 230, 230, 230, 231, 231,
  238. 231, 232, 232, 232, 233, 233, 233, 234, 234, 234, 235, 235, 235, 236, 236, 236,
  239. 237, 237, 237, 238, 238, 238, 239, 239, 239, 240, 240, 240, 241, 241, 241, 242,
  240. 242, 242, 243, 243, 243, 244, 244, 244, 245, 245, 245, 246, 246, 246, 247, 247,
  241. 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 253, 254, 254, 255, 255 };
  242. private int lut_Green_int[] = {
  243. 143, 143, 142, 142, 141, 141, 140, 140, 139, 139, 138, 138, 137, 137, 136, 136,
  244. 135, 135, 135, 134, 134, 134, 133, 133, 133, 132, 132, 132, 131, 131, 131, 130,
  245. 130, 130, 129, 129, 129, 128, 128, 128, 127, 127, 127, 126, 126, 126, 125, 125,
  246. 125, 124, 124, 124, 123, 123, 123, 122, 122, 122, 121, 121, 121, 120, 120, 120,
  247. 119, 119, 119, 118, 118, 118, 117, 117, 117, 116, 116, 116, 115, 115, 115, 114,
  248. 114, 114, 113, 113, 113, 112, 112, 112, 111, 111, 111, 110, 110, 110, 109, 109,
  249. 109, 108, 108, 108, 107, 107, 107, 106, 106, 106, 105, 105, 105, 104, 104, 104,
  250. 103, 103, 103, 102, 102, 102, 101, 101, 101, 100, 100, 100, 99, 99, 99, 98,
  251. 98, 98, 97, 97, 97, 96, 96, 96, 95, 95, 95, 94, 94, 94, 93, 93,
  252. 93, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89, 89, 89, 88, 88, 88,
  253. 87, 87, 87, 86, 86, 86, 85, 85, 85, 84, 84, 84, 83, 83, 83, 82,
  254. 82, 82, 81, 81, 81, 80, 80, 80, 79, 79, 79, 78, 78, 78, 77, 77,
  255. 77, 76, 76, 76, 75, 75, 75, 74, 74, 74, 73, 73, 73, 72, 72, 72,
  256. 71, 71, 71, 70, 70, 70, 69, 69, 69, 68, 68, 68, 67, 67, 67, 65,
  257. 65, 65, 64, 64, 64, 63, 63, 63, 62, 62, 62, 60, 60, 60, 59, 59,
  258. 57, 57, 56, 56, 54, 54, 52, 52, 50, 50, 49, 49, 47, 47, 44, 44 };
  259. private byte[] lut_Red, lut_Green; // Unsigned (0-255) in OpenCV
  260. @Override
  261. public void onCameraViewStarted(int width, int height) {
  262. cam_width = width;
  263. cam_height = height;
  264. cam_half_width = width/2;
  265. cam_quarter_width = cam_half_width/2;
  266. half_rect = new Rect(0,0,cam_half_width, cam_height);
  267. srcL_rect = new Rect(0,0,cam_half_width, cam_height);
  268. srcR_rect = new Rect(separation,0,cam_half_width, cam_height);
  269. dstL_rect = new Rect(0,0, cam_half_width, cam_height);
  270. dstR_rect = new Rect(cam_half_width,0, cam_half_width, cam_height);
  271. img_stereo = new Mat(cam_height, cam_width, CvType.CV_8UC4);
  272. img_filtered = new Mat(cam_height, cam_width, CvType.CV_8UC4);
  273. img_zero = Mat.zeros(cam_height, cam_width, CvType.CV_8U);
  274. imgtype = 1;
  275. //used_gray = true;
  276. used_rgba = false; used_invgray = false; used_isolumRG = false; //used_sobels = false;
  277. img_gray = new Mat(cam_height, cam_width, CvType.CV_8U);
  278. // For controlling time
  279. img_sobel01 = new Mat(cam_height, cam_width, CvType.CV_16S);
  280. img_sobel10 = new Mat(cam_height, cam_width, CvType.CV_16S);
  281. img_temp8UC = new Mat(cam_height, cam_width, CvType.CV_8U);
  282. img_noise = new Mat(cam_height, cam_width, CvType.CV_32F);
  283. img_gray32F = new Mat(cam_height, cam_width, CvType.CV_32F);
  284. lut_Red = new byte[256];
  285. lut_Green = new byte[256];
  286. for (int i = 0; i < 256; i++) {
  287. lut_Red[i] = (byte) (lut_Red_int[i] & 0xFF);
  288. lut_Green[i] = (byte) (lut_Green_int[i] & 0xFF);
  289. }
  290. mat_lut_Red = new Mat(256, 1, CvType.CV_8UC1);
  291. mat_lut_Red.put(0, 0, lut_Red);
  292. mat_lut_Green = new Mat(256, 1, CvType.CV_8UC1);
  293. mat_lut_Green.put(0, 0, lut_Green);
  294. Log.d(LOGTAG,"(Width, Height)=("+Integer.toString(width)+", "+Integer.toString(height)+")");
  295. Log.d(LOGTAG,"(HWidth, QWidth)=("+Integer.toString(cam_half_width)+", "+Integer.toString(cam_quarter_width)+")");
  296. }
  297. @Override
  298. public void onCameraViewStopped() {
  299. img_zero.release();
  300. img_stereo.release();
  301. img_filtered.release();
  302. mat_lut_Red.release();
  303. mat_lut_Green.release();
  304. if(used_rgba==true) {
  305. img_rgba.release();
  306. channels_rgba.get(0).release();
  307. channels_rgba.get(1).release();
  308. channels_rgba.get(2).release();
  309. channels_rgba.get(3).release();
  310. }
  311. img_gray.release();
  312. img_sobel01.release();
  313. img_sobel10.release();
  314. img_temp8UC.release();
  315. img_noise.release();
  316. img_gray32F.release();
  317. if(used_invgray==true) img_invgray.release();
  318. if(used_isolumRG==true) {
  319. img_isolumR.release();
  320. img_isolumG.release();
  321. }
  322. }
  323. @Override
  324. public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
  325. img_gray = inputFrame.gray();
  326. if(used_rgba==true) {
  327. img_rgba = inputFrame.rgba();
  328. Core.split(img_rgba, channels_rgba);
  329. }
  330. if(used_invgray==true) Core.bitwise_not(img_gray,img_invgray);
  331. //Imgproc.Canny(img_gray, img_filtered, 50, 100*3);
  332. double adjust = 0.2;
  333. switch(imgtype) {
  334. case 0: // RGB
  335. Core.merge(new ArrayList<>(Arrays.asList(channels_rgba.get(0), channels_rgba.get(1), channels_rgba.get(2), img_zero)), img_filtered);
  336. break;
  337. case 1: // Gray
  338. Core.merge(new ArrayList<>(Arrays.asList(img_gray, img_gray, img_gray, img_zero)), img_filtered);
  339. break;
  340. case 2: // Red Only
  341. Core.LUT(img_gray, mat_lut_Red, img_isolumR);
  342. Core.merge(new ArrayList<>(Arrays.asList(img_isolumR, img_zero, img_zero, img_zero)), img_filtered);
  343. break;
  344. case 3: // Red-inv Only
  345. Core.LUT(img_invgray, mat_lut_Red, img_isolumR);
  346. Core.merge(new ArrayList<>(Arrays.asList(img_isolumR, img_zero, img_zero, img_zero)), img_filtered);
  347. break;
  348. case 4: // Green Only
  349. Core.LUT(img_invgray, mat_lut_Green, img_isolumG);
  350. Core.merge(new ArrayList<>(Arrays.asList(img_zero, img_isolumG, img_zero, img_zero)), img_filtered);
  351. break;
  352. case 5: // Green-inv Only
  353. Core.LUT(img_gray, mat_lut_Green, img_isolumG);
  354. Core.merge(new ArrayList<>(Arrays.asList(img_zero, img_isolumG, img_zero, img_zero)), img_filtered);
  355. break;
  356. case 6: // Red-Green
  357. Core.LUT(img_gray, mat_lut_Red, img_isolumR);
  358. Core.LUT(img_gray, mat_lut_Green, img_isolumG);
  359. Core.merge(new ArrayList<>(Arrays.asList(img_isolumR, img_isolumG, img_zero, img_zero)), img_filtered);
  360. break;
  361. case 7: // Green-Red
  362. Core.LUT(img_invgray, mat_lut_Red, img_isolumR);
  363. Core.LUT(img_invgray, mat_lut_Green, img_isolumG);
  364. Core.merge(new ArrayList<>(Arrays.asList(img_isolumR, img_isolumG, img_zero, img_zero)), img_filtered);
  365. break;
  366. case 8: // Contour
  367. Imgproc.GaussianBlur(img_gray, img_temp8UC, new Size(3,3), 0, 0, BORDER_DEFAULT);
  368. Imgproc.Sobel(img_temp8UC, img_sobel01, CvType.CV_16S, 0,1);
  369. Imgproc.Sobel(img_temp8UC, img_sobel10, CvType.CV_16S, 1,0);
  370. Core.convertScaleAbs(img_sobel01, img_sobel01);
  371. Core.convertScaleAbs(img_sobel10, img_sobel10);
  372. Core.addWeighted(img_sobel01, 1, img_sobel10, 1, 0, img_temp8UC); // Thresholded at 255
  373. //Imgproc.threshold(img_temp8UC,img_temp8UC,70,255,THRESH_TOZERO);
  374. Core.merge(new ArrayList<>(Arrays.asList(img_temp8UC, img_temp8UC, img_temp8UC, img_zero)), img_filtered);
  375. break;
  376. case 9: // 1st order
  377. Core.randu(img_noise,0, 0.5+adjust/2.0);
  378. img_gray.convertTo(img_gray32F, CvType.CV_32F);
  379. Core.normalize(img_gray32F, img_gray32F, 0, 1, Core.NORM_MINMAX, CvType.CV_32F);
  380. Core.multiply(img_gray32F, new Scalar(1.0 - (0.5+adjust/2.0)), img_gray32F);
  381. Core.add(img_gray32F, img_noise, img_gray32F);
  382. Core.pow(img_gray32F,1.0/2.218, img_gray32F);
  383. Core.multiply(img_gray32F, new Scalar(255), img_gray32F);
  384. img_gray32F.convertTo(img_temp8UC, CvType.CV_8UC1);
  385. Core.merge(new ArrayList<>(Arrays.asList(img_temp8UC, img_temp8UC, img_temp8UC, img_zero)), img_filtered);
  386. break;
  387. case 10: // 2nd-order (LowContrast -> HighContrast)
  388. Core.randu(img_noise,-0.5,+0.5);
  389. img_gray.convertTo(img_gray32F, CvType.CV_32F);
  390. Core.multiply(img_gray32F, new Scalar(1.0 - adjust), img_gray32F);
  391. Core.add(img_gray32F, new Scalar(255*adjust), img_gray32F);
  392. Core.multiply(img_gray32F, img_noise, img_gray32F);
  393. Core.normalize(img_gray32F, img_gray32F, 0, 1, Core.NORM_MINMAX, CvType.CV_32F);
  394. Core.pow(img_gray32F,1.0/2.218, img_gray32F);
  395. Core.multiply(img_gray32F, new Scalar(255), img_gray32F);
  396. img_gray32F.convertTo(img_temp8UC, CvType.CV_8UC1);
  397. Core.merge(new ArrayList<>(Arrays.asList(img_temp8UC, img_temp8UC, img_temp8UC, img_zero)), img_filtered);
  398. break;
  399. case 11: // 2nd-order-inv (LowContrast -> HighContrast)
  400. Core.randu(img_noise,-0.5,+0.5);
  401. img_invgray.convertTo(img_gray32F, CvType.CV_32F);
  402. Core.multiply(img_gray32F, new Scalar(1.0 - adjust), img_gray32F);
  403. Core.add(img_gray32F, new Scalar(255*adjust), img_gray32F);
  404. Core.multiply(img_gray32F, img_noise, img_gray32F);
  405. Core.normalize(img_gray32F, img_gray32F, 0, 1, Core.NORM_MINMAX, CvType.CV_32F);
  406. Core.pow(img_gray32F,1.0/2.218, img_gray32F);
  407. Core.multiply(img_gray32F, new Scalar(255), img_gray32F);
  408. img_gray32F.convertTo(img_temp8UC, CvType.CV_8UC1);
  409. Core.merge(new ArrayList<>(Arrays.asList(img_temp8UC, img_temp8UC, img_temp8UC, img_zero)), img_filtered);
  410. break;
  411. default: // 12: Default == Gray-inv
  412. Core.merge(new ArrayList<>(Arrays.asList(img_invgray, img_invgray, img_invgray, img_zero)), img_filtered);
  413. break;
  414. }
  415. srcL_rect = new Rect(cam_quarter_width-separation/2,0, cam_half_width, cam_height);
  416. srcR_rect = new Rect(cam_quarter_width+separation/2,0, cam_half_width, cam_height);
  417. img_filtered.submat(srcL_rect).copyTo(img_stereo.submat(dstL_rect));
  418. img_filtered.submat(srcR_rect).copyTo(img_stereo.submat(dstR_rect));
  419. if(capture==1) // Contour test!!
  420. {
  421. File savePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); // "storage/emulated/0/Pictures" in Internal storage
  422. File saveDir = new File(savePath + "/OCV/"); // "storage/emulated/0/Pictures/OCV" in Internal storage
  423. Log.d(LOGTAG,"saveDir="+saveDir);
  424. if(!saveDir.exists()) saveDir.mkdirs();
  425. String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
  426. Mat imt_output = new Mat(cam_height, cam_width, CvType.CV_8UC4);
  427. if(used_rgba==false) {
  428. img_rgba = new Mat(cam_height, cam_width, CvType.CV_8UC4);
  429. img_rgba = inputFrame.rgba();
  430. Imgcodecs.imwrite(saveDir + "/" + timeStamp+"_rgba.png", img_rgba);
  431. img_rgba.release();
  432. } else
  433. Imgcodecs.imwrite(saveDir + "/" + timeStamp+"_rgba.png", img_rgba);
  434. Imgcodecs.imwrite(saveDir + "/" + timeStamp+"_gray.png", img_gray);
  435. capture = 0;
  436. ToneGenerator toneG = new ToneGenerator(AudioManager.STREAM_ALARM, 100);
  437. toneG.startTone(ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD, 200);
  438. imt_output.release();
  439. if(used_rgba==false) img_rgba.release();
  440. }
  441. return img_stereo;
  442. }
  443. };
  444. @Override
  445. public void onPause() {
  446. super.onPause();
  447. if(mOpenCvCameraView!=null) {
  448. mOpenCvCameraView.disableView();
  449. }
  450. }
  451. @Override
  452. public void onResume() {
  453. super.onResume();
  454. if(!OpenCVLoader.initDebug()) {
  455. Log.d(LOGTAG, "OpenCV not found, Initializing");
  456. OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION,this,mLoaderCallback);
  457. } else {
  458. mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
  459. }
  460. }
  461. @Override
  462. public void onDestroy() {
  463. super.onDestroy();
  464. if(mOpenCvCameraView!=null) {
  465. mOpenCvCameraView.disableView();
  466. }
  467. }
  468. }

ARNeurosci AndroidApp.java, no license · at the source

Overview

Authors: Tadamasa Sawada1,2, Maria Dvoeglazova3, Alla Zargaryan2,4, Anna Tamrazyan2, Valeria G Kozhevnikova3, Asya Berberyan2, Matteo Feurra5, Elena S Gorbunova3
  1. Zaven P. and Sonia Akian College of Science and Engineering, American University of Armenia, Yerevan, Armenia
  2. Department of Psychology, Russian-Armenian (Slavonic) University, Yerevan, Armenia
  3. School of Psychology, HSE University, Moscow, Russia
  4. Faculty of Education Psychology and Sociology, Armenian State Pedagogical University, Yerevan, Armenia
  5. Centre for Cognition and Decision Making, Institute for Cognitive Neuroscience, HSE University, Moscow, Russia
Journal: Frontiers in neuroscience, volume 20, article 1925212
Dates: received 1 July 2026; accepted 25 August 2026; published online 22 September 2026
Type: Review · Language: English
License: CC BY
Identifiers: DOI · PMCID PMC13640456
Status: code verified (how the code is found and verified)
Methods: Spectral & time-frequency, Complexity, Physiology & signal measures
Keywords: Augmented Reality (AR), brain stimulation, extended reality, field study, virtual reality (VR), XR
Citations: not cited yet (Europe PMC); 199 references in the paper

Abstract

This study reviews the behavioral techniques that control visual stimuli to systematically modulate visual processing in an observer’s brain. These techniques are indirect but more affordable than more-direct techniques for stimulating the brain. The limitations of these techniques and the calibrations necessary for them are also discussed. Some of the behavioral techniques can be also used in field studies by making use of Augmented Reality (AR) technology and a head-mounted display (HMD). The AR HMDs for the behavioral techniques was assembled by combining a smartphone and a wearable stereoscope, both of which were also affordable, as a proof-of-concept. The reviewed behavioral techniques make it possible that researchers with limited budgets can conduct neuroscience studies and that students can learn about these subjects in low-income countries or in underfunded institutions. It can contribute to the democratization of neuroscience and the global equity of scientific research, as well as to broadening the populations studied in cognitive and neuroscience.

Reproduced under the paper's license (CC BY), from the paper cited above.

Repository

Its files are read in the Code ↔ Paper reader above.

OSF hz7b9

License: none: the authors keep all their rights
State: the link answers, verified on 7 October 2026
Evidence: files inventoried
Languages: Java (1)
Size: 5 files, 1 script
Software Heritage: not checked
Found in: the text, “AR implementation of some of the behavioral tech”
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Availability: 1 check, the latest on 7 October 2026: the link answers (HTTP 200)
  • 7 October 2026: the link answers (HTTP 200)
1 file
At the source: osf.io/hz7b9/

Tracing map

Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.

What the map holds:

  • 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 1 script, each with its path and the digest of its content;
  • no match between paragraphs and code yet;
  • neither the text of the paper nor the code itself.

Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.

Data

No dataset and no data link were found in the paper.

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 1, 7 October 2026: the first record

Recorded: type, language, journal, volume, pages, dates, 8 authors, 6 keywords, 186 references.

Cite

This paper

Sawada, T., Dvoeglazova, M., Zargaryan, A., Tamrazyan, A., Kozhevnikova, V. G., Berberyan, A., Feurra, M., & Gorbunova, E. S. (2026). Behavioral techniques for controlling visual stimuli to modulate visual processing in the brain and their implementation in augmented reality technology. Frontiers in neuroscience, 20, 1925212.

BibTeX

@article{sawada2026behavioral,
author = {Sawada, Tadamasa and Dvoeglazova, Maria and Zargaryan, Alla and Tamrazyan, Anna and Kozhevnikova, Valeria G and Berberyan, Asya and Feurra, Matteo and Gorbunova, Elena S},
title = {{Behavioral techniques for controlling visual stimuli to modulate visual processing in the brain and their implementation in augmented reality technology}},
journal = {Frontiers in neuroscience},
year = {2026},
month = oct,
volume = {20},
pages = {1925212},
publisher = {Frontiers Media SA},
issn = {1662-4548},
pmcid = {PMC13640456}
}

RIS

TY - JOUR
AU - Sawada, Tadamasa
AU - Dvoeglazova, Maria
AU - Zargaryan, Alla
AU - Tamrazyan, Anna
AU - Kozhevnikova, Valeria G
AU - Berberyan, Asya
AU - Feurra, Matteo
AU - Gorbunova, Elena S
TI - Behavioral techniques for controlling visual stimuli to modulate visual processing in the brain and their implementation in augmented reality technology
T2 - Frontiers in neuroscience
J2 - Front Neurosci
PY - 2026
DA - 2026/10/07
VL - 20
SP - 1925212
SN - 1662-4548
PB - Frontiers Media SA
LA - en
ER -

CSL-JSON

{
"id": "pmcid:PMC13640456",
"type": "article-journal",
"title": "Behavioral techniques for controlling visual stimuli to modulate visual processing in the brain and their implementation in augmented reality technology",
"container-title": "Frontiers in neuroscience",
"author": [
{
"family": "Sawada",
"given": "Tadamasa"
},
{
"family": "Dvoeglazova",
"given": "Maria"
},
{
"family": "Zargaryan",
"given": "Alla"
},
{
"family": "Tamrazyan",
"given": "Anna"
},
{
"family": "Kozhevnikova",
"given": "Valeria G"
},
{
"family": "Berberyan",
"given": "Asya"
},
{
"family": "Feurra",
"given": "Matteo"
},
{
"family": "Gorbunova",
"given": "Elena S"
}
],
"container-title-short": "Front Neurosci",
"volume": "20",
"page": "1925212",
"PMCID": "PMC13640456",
"ISSN": "1662-4548",
"publisher": "Frontiers Media SA",
"language": "en",
"issued": {
"date-parts": [
[
2026,
10,
7
]
]
}
}

The tracing map gets a citation of its own once an author has validated it and it has a DOI.

Similar papers

The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.

[1] doi:10.3758/s13414-024-02866-x
Involvement of the superior colliculi in crossmodal correspondences.
Journal: Attention, perception & psychophysics
In common: 8 references
[2] doi:10.1371/journal.pcbi.1011704 [code]
Normalization by orientation-tuned surround in human V1-V3.
Journal: PLoS computational biology
In common: 6 references
[3] doi:10.3389/fnins.2023.1200661 [code]
A mechanistic account of visual discomfort.
Journal: Frontiers in neuroscience
In common: 6 references
[4] doi:10.1038/s42003-025-08871-6 [code]
Spatially global effects of feature-based attention in functional subdivisions of human subcortical nuclei.
Journal: Communications biology
In common: 5 references
[5] doi:10.1038/s42003-023-04912-0 [code]
Correlated variability in primate superior colliculus depends on functional class.
Journal: Communications biology
In common: 5 references
[6] doi:10.3390/brainsci14080753
Neural Substrates for Early Data Reduction in Fast Vision: A Psychophysical Investigation.
Journal: Brain sciences
In common: 5 references
[7] doi:10.1038/s41598-025-07644-9
Optimal feature encoding in early vision.
Journal: Scientific reports
In common: 5 references
[8] doi:10.1098/rstb.2021.0512 [code]
A deep neural network model of the primate superior colliculus for emotion recognition.
Journal: Philosophical transactions of the Royal Society of London. Series B, Biological sciences
In common: 4 references
[9] doi:10.1073/pnas.2120581119 [code]
Divisive normalization is an efficient code for multivariate Pareto-distributed environments.
Journal: Proceedings of the National Academy of Sciences of the United States of America
In common: 5 references
[10] doi:10.1371/journal.pbio.3002375 [code]
Human subcortical pathways automatically detect collision trajectory without attention and awareness.
Journal: PLoS biology
In common: 4 references

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

Add the badge to the code's README

OSCR: the badge of this paper

If you are an author or a maintainer of this paper's code, you can add this badge. It says what OSCR knows of the paper (its code, its validated tracing map) and links the code to this page. Paste one of these snippets under the README's title. Keep the two marks around it, so that the badge can be replaced in place and is never added twice. OSCR changes nothing in your repository.

Markdown
<!-- oscr-badge:start -->
[![OSCR](https://openscicode.org/badge/repo/osf:hz7b9.svg)](https://openscicode.org/badge/repo/osf:hz7b9)
<!-- oscr-badge:end -->
reStructuredText
.. oscr-badge:start

.. image:: https://openscicode.org/badge/repo/osf:hz7b9.svg
   :target: https://openscicode.org/badge/repo/osf:hz7b9
   :alt: OSCR

.. oscr-badge:end
HTML
<!-- oscr-badge:start -->
<a href="https://openscicode.org/badge/repo/osf:hz7b9"><img src="https://openscicode.org/badge/repo/osf:hz7b9.svg" alt="OSCR"></a>
<!-- oscr-badge:end -->

If you choose to, you can have the badge kept up to date for you, with oscr badge --write from the command line or with the GitHub Action in your repository's workflows. Every other form and option (a card, AsciiDoc, LaTeX, shields.io) is on the badge page.

Request its removal

To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).

Discussion, reproductions, activity

Discussion: code errors and mismatches between the code and the paper about this paper and its code, from readers and its authors, beside the paper and its tracing map.

Report a mismatch between the code and the paper · Report a code error (signed in)

Reproductions: reports from readers who ran the authors' code and did not get the paper's result, what they ran, with which environment, commit and data.

Report a reproduction failure (signed in)

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.