preface

Baidu’s verification code and double 叒 update. Of course, out of curiosity, the cat picked up the keyboard again and began the challenge.

Here comes the text.

Let’s take a look at what changes baidu’s bigwig has made since cracking the rotation verification code last time.

1. Mosaic is added when capturing pictures. 2

Mosaic was added to capture the picture

  • The screenshot is from this subchild

  • Backstage got this guy’s

Oh, there’s something about this Mosaic

Picture down are not the same as how to identify, Baidu here is also painstakingly, give you a thumbs-up.

Then again, even that doesn’t bother us, so here I think there are a few other ways to get this image:

  • 1. Use the system-level mouse
  • 2. Obtain the url from the screenshot

1. Use the system-level mouse

First, I tried the first way

Locate the image path to get the image path, and then call another page through the simulator

Then save the image with this code (used here)RobotSystem-level mouse control class)

public byte[] sivePic(String url, WebDriver driver, String window_one) {
		((JavascriptExecutor) driver).executeScript("window.open('" + url + "')"); // Open a new window with js
		sleep(2000);
		Set<String> allWindow = driver.getWindowHandles(); // Get all window handles
		sleep(1 * 500);
		for (String i : allWindow) {
			if(i ! = window_one) { driver.switchTo().window(i); } } WebElement img = driver.findElement(By.tagName("img"));
		Actions actions = new Actions(driver);
		Robot robot;
		byte[] picBytes = null;
		File imgFile = null;
		// Declare a StingSelection object and instantiate it with a String argument;
		String imgName = "baidu_" + System.currentTimeMillis()+".jpg";
		// Use setContents of the Toolkit object to place the string into the stickboard;
		Toolkit.getDefaultToolkit().getSystemClipboard().setContents( new StringSelection(imgName), null);
		try {
			robot = new Robot();
			robot.setAutoDelay(100);
			actions.moveToElement(img).contextClick().perform();
			sleep(100);
			robot.keyPress(KeyEvent.VK_DOWN);
			sleep(100);
			robot.keyRelease(KeyEvent.VK_DOWN);
			sleep(100);
			robot.keyPress(KeyEvent.VK_DOWN);
			sleep(100);
			robot.keyRelease(KeyEvent.VK_DOWN);
			sleep(100);
			/ / confirm
			robot.keyPress(KeyEvent.VK_ENTER);
			robot.keyRelease(KeyEvent.VK_ENTER);
			sleep(1000);
			/ / delete
			robot.keyPress(KeyEvent.VK_DELETE);
			robot.keyRelease(KeyEvent.VK_DELETE);
			sleep(500);
			// Press CRTL v;
			robot.keyPress(KeyEvent.VK_CONTROL);
			robot.keyPress(KeyEvent.VK_V);
			sleep(500);
			// Release CRTL v key
			robot.keyRelease(KeyEvent.VK_V);
			robot.keyRelease(KeyEvent.VK_CONTROL);
			sleep(500);
			// Confirm the file name
			robot.keyPress(KeyEvent.VK_ENTER);
			robot.keyRelease(KeyEvent.VK_ENTER);
			sleep(5000);
			String name = System.getenv().get("USERNAME");
			imgFile = new File("C:/Users/" + name + "/Downloads/"+imgName);
			picBytes = FileUtils.readFileToByteArray(imgFile);
			System.out.println("save ok");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			imgFile.delete();
		}
		return picBytes;
	}
Copy the code

Uh-huh, got it.

Thought that was the end of it.

Unexpectedly, after catching a few pieces of Mosaic appeared again…

At this point, the first method is defeated.

2. Obtain the url from the screenshot

This method is more reliable, Baidu can not let users see Mosaic pictures, ha ha (manual dog head)

// Get the random number of ID
WebElement vcodesElemet = driver.findElement(By.className("mod-vcodes"));
String num = vcodesElemet.getAttribute("id");
num = num.split("mod-vcodes")[num.split("mod-vcodes").length - 1];
WebElement imgElemet = driver.findElement(By.id("vcode-spin-img" + num));
File img = getImgFile(driver, imgElemet.getLocation().getX() - 8,imgElemet.getLocation().getY());
Copy the code
152 is the actual width and height of the image displayed on the page */
private File getImgFile(WebDriver driver, int i, int j) {
	BufferedImage imgbuf = null;
	File srcFile, imgFile = null;
	try {
		srcFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
		imgbuf = ImageIO.read(srcFile).getSubimage(i, j, 152.152);
		imgFile = new File("C:\\daidu_" + System.currentTimeMillis() + ".png");
		ImageIO.write(imgbuf, "png", imgFile);
	} catch (IOException e) {
		e.printStackTrace();
	}
	return imgFile;
}
Copy the code

So at this point we have a validation image, which is definitely not as sharp as the original image, so the recognition rate is a little bit lower. But not too much.

I’m going to grab the picture here and I’m done.

Added photo gallery

It’s not a big deal when it comes to adding a gallery, as long as you grab an image, you can rotate it to create the corresponding image, you just need to find different images.

Before, Baidu had about 50-60 different images, that is to say, different angles (360°) were all added into the image library at most 21600 images (estimated value).

Now through the capture of hundreds of pictures to observe, there are about 120 different pictures, the previous 50-60 are also included, that is to say, Baidu has doubled the gallery. It’s about 43,000 images.

There is no big problem here, just that our model library needs to be updated.


The division line of the classics


Good since the problem above was solved, so say next specific crack thinking and step.

  1. A large number of images are captured and screened
  2. Generate model library from filtered images
  3. Plug the model library into the automated simulator

Well, it’s not that complicated. Open to ~

First, capture a large number of pictures and screen

The above mentioned capture pictures we use the way of screenshots, automation procedures here will not put first, there is a complete code at the back of the article. Let’s take a look at the results.

You can see that there are a lot of similar images, and we can basically find all the different images with about 300 to 500, and then just keep one of the similar images.

Second, generate the model library according to the screened pictures

  1. Here, we take the pictures screened from step 1, rotate each piece to generate 360 degree pictures from various angles, and calculate the sliding distance from the original picture to the corresponding Angle by proportion.

  1. Then find the positive graph in each model library and mark the previously marked distance value to the original graph.

  1. Then calculate the distance of each graph in the model library and mark it.

In order to improve efficiency, we stored the model library in the form of map object in.obj file. When starting the program, you only need to read a file and save it to the map, greatly improving the identification efficiency.

Model library: Baidu_mod.obj

Connect the model library to the automated simulator

  1. Automatic simulator
public class Baidu {
	private final static Logger logger = LoggerFactory.getLogger(BaiduTrain.class);
	private final String INDEX_URL = "http://passport.baidu.com/?getpassindex&tt=1597054938536&gid=00C700C-A457-4CCF-8588-F118FFF70829&tpl=mn&u=https%3A%2F%2 Fwww.baidu.com%2Fs%3Fie%3DUTF-8";
	private static Map<String, Map<String, PicFinger>> Map = new HashMap<String, Map<String, PicFinger>>();
	/** * Screenshot (verification code) */
	private File getImgFile(WebDriver driver, int i, int j) {
		BufferedImage imgbuf = null;
		File srcFile, imgFile = null;
		try {
			srcFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
			imgbuf = ImageIO.read(srcFile).getSubimage(i, j, 152.152);
			imgFile = new File("C:\\daidu_" + System.currentTimeMillis() + ".png");
			ImageIO.write(imgbuf, "png", imgFile);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return imgFile;
	}
	// Change the image to a comparable object
	public static PicFinger getPicFinger(File file) {
		try {
			BufferedImage libBuf = ImageIO.read(file);
			PicFinger picFinger = new PicFinger(libBuf);
			byte[] img = picFinger.getBinaryzationMatrix();
			PicFinger fp = new PicFinger(img);
			return fp;
		} catch (IOException e) {
			e.printStackTrace();
			return null; }}// Match the model library to get the sliding distance
	public String getDistance(File file) {
		double succRate = 80;
		float ret, maxRet = -1;
		PicFinger picFinger = getPicFinger(file);
		PicFinger fpSrc = null;
		String distance = "";
		for (String mapkey : Map.keySet()) {
			for (String key : Map.get(mapkey).keySet()) {
				fpSrc = Map.get(mapkey).get(key);
				ret = picFinger.compare(fpSrc) * 100;
				if (ret >= succRate) {
					if (ret > maxRet) {
						maxRet = ret;
						distance = key.substring(key.indexOf(The '-') + 1, key.length());
					}
				}
			}
		}
		System.out.println("The highest similarity degree is:" + maxRet + "|distance=" + distance);
		return distance;
	}
	// Automatic program
	public void seleniumTest(a) {
		String phone = "13888888888";
		ChromeDriverManager manager = ChromeDriverManager.getInstance();
		String gtText = null, num;
		Integer distance = 30;
		int status = -1;
		By moveBy, gtTextBy, submit, phoneBy, securemobil, close, tipInfo;
		WebElement moveElemet, submitElemet, gtTextElement, phoneElemet, securemobilElemet, closeElemet, tipInfoElemet, vcodesElemet;
		WebDriver driver = null;
		try {
			driver = manager.getDriver();
			driver.get(INDEX_URL);
			sleep(1 * 500);
			driver.navigate().refresh();
			sleep(1 * 500);
			// Enter your mobile phone number
			phoneBy = By.id("account");
			phoneElemet = waitWebElement(driver, phoneBy, 400);
			if (phoneElemet == null)
				return null;
			phoneElemet.clear();
			for (int i = 0; i < phone.length(); i++) {
				char c = phone.charAt(i);
				phoneElemet.sendKeys(c + "");
				phoneElemet.click();
			}
			/ / the next step
			submit = By.id("submit");
			submitElemet = waitWebElement(driver, submit, 400);
			if (submitElemet == null)
				return null;
			submitElemet.click();
			// Click close
			close = By.xpath("//div[@class='vcode-close']");
			closeElemet = waitWebElement(driver, close, 200);
			if (closeElemet == null)
				return null;
			if(closeElemet ! =null)
				closeElemet.click();
			// Click to select the phone number
			securemobil = By.xpath("//p[@s='securemobil']");
			securemobilElemet = waitWebElement(driver, securemobil, 200);
			if (securemobilElemet == null)
				return null;
			if(securemobilElemet ! =null && securemobilElemet.isDisplayed())
				securemobilElemet.click();
			/ / the next step
			submit = By.id("submit");
			submitElemet = waitWebElement(driver, submit, 200);
			if (submitElemet == null)
				return null;
			submitElemet.click();
			// Get the random number of ID
			vcodesElemet = waitWebElement(driver, By.className("mod-vcodes"), 200);
			if (vcodesElemet == null)
				return null;
			num = vcodesElemet.getAttribute("id");
			num = num.split("mod-vcodes")[num.split("mod-vcodes").length - 1];

			tipInfo = By.id("pass-slide-tipInfo2" + num);
			tipInfoElemet = waitWebElement(driver, tipInfo, 200);
			if (tipInfoElemet == null)
				return null;
			if (tipInfoElemet.getText().contains("The right")) {
				// Click close
				close = By.className("vcode-close");
				closeElemet = waitWebElement(driver, close, 200);
				if (closeElemet == null)
					return null;
				closeElemet.click();
				/ / the next step
				submit = By.id("submit");
				submitElemet = waitWebElement(driver, submit, 200);
				if (submitElemet == null)
					return null;
				submitElemet.click();
				// Get the random number of ID
				vcodesElemet = waitWebElement(driver, By.className("mod-vcodes"), 200);
				if (vcodesElemet == null)
					return null;
				num = vcodesElemet.getAttribute("id");
				num = num.split("mod-vcodes")[num.split("mod-vcodes").length - 1];
			}
			for (int i = 0; i < 100; i++) {
				// Get the slide button
				moveBy = By.id("vcode-spin-button" + num);
				moveElemet = waitWebElement(driver, moveBy, 400);
				if(moveElemet ! =null) {
					moveElemet.click();
				} else {
					System.out.println("error get moveElemet=" + moveElemet);
					break;
				}
				sleep(100);
				WebElement imgElemet = driver.findElement(By.id("vcode-spin-img" + num));
				File img = getImgFile(driver, imgElemet.getLocation().getX() - 8, imgElemet.getLocation().getY());
				distance = Integer.parseInt(getDistance(img));
				/ / sliding
				move(driver, moveElemet, distance);
				sleep(100);
				// get the slide result for 10s
				boolean isWaitLoad = false;
				for (int k = 0; k < 100; k++) {
					gtTextBy = By.id("vcode-spin-icon" + num);
					gtTextElement = waitWebElement(driver, gtTextBy, 400);
					if (gtTextElement == null)
						return null;
					gtText = gtTextElement.getAttribute("class");
					if (gtText.contains("loading") || gtText.contains("hide")) {
						if(! isWaitLoad) { System.out.print("loading(" + gtTextBy.toString() + ")");
							isWaitLoad = true;
						}
						System.out.print(".");
						sleep(100);
						continue;
					} else
						break;
				}
				if (gtText.contains("success")) {
					sleep(100);
					break;
				}
				sleep(2000); }}catch (Exception e) {
			e.printStackTrace();
		} finally {
			sleep(1000); manager.closeDriver(status); }}// Thread sleep
	private static void sleep(long millis) {
		try {
			Thread.sleep(millis);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch blocke.printStackTrace(); }}/** * simulates manual movement **@param driver
	 * @paramElement page slider *@paramDistance requires moving distance */
	private static void move(WebDriver driver, WebElement element, int distance) throws InterruptedException {
		int randomTime = 0;
		if (distance > 90)
			randomTime = 250;
		else if (distance > 80 && distance <= 90)
			randomTime = 150;
		List<Integer> track = GeetCanvasApi.getMoveTrack(distance);
		int moveY = 1;
		try {
			Actions actions = new Actions(driver);
			actions.clickAndHold(element).perform();
			Thread.sleep(200);
			for (int i = 0; i < track.size(); i++) {
				actions.moveByOffset(track.get(i), moveY).perform();
				Thread.sleep(new Random().nextInt(300) + randomTime);
			}
			Thread.sleep(200);
			actions.release(element).perform();
		} catch (Exception e) {
			logger.error("move:err = "+ e.toString()); }}// delay loading
	private static WebElement waitWebElement(WebDriver driver, By by, int count) {
		WebElement webElement = null;
		boolean isWait = false;
		for (int k = 0; k < count; k++) {
			try {
				webElement = driver.findElement(by);
				if (isWait)
					System.out.println(" ok!");
				return webElement;
			} catch (org.openqa.selenium.NoSuchElementException | org.openqa.selenium.ElementNotVisibleException ex) {
				isWait = true;
				if (k == 0)
					System.out.print("waitWebElement(" + by.toString() + ")");
				else
					System.out.print(".");
				sleep(50); }}if (isWait) {
			System.out.println(" outTime!");
			logger.error("WebElement = null");
		}
		return null;
	}
	// Read the file to read the model library
	public static Object load(String file) throws Exception {
		FileInputStream freader = null;
		ObjectInputStream objectInputStream = null;
		try {
			freader = new FileInputStream(file);
			objectInputStream = new ObjectInputStream(freader);
			Object o = objectInputStream.readObject();
			return o;
		} catch (Exception e) {
			return null;
		} finally {
			if(freader ! =null)
				freader.close();
			if(objectInputStream ! =null) objectInputStream.close(); }}@SuppressWarnings("unchecked")
	public static void main(String[] args) throws Exception {
		Map = (Map<String, Map<String, PicFinger>>) load("C:\\baidu_mod.obj");
		OCRUtil.chromePath = "C://chrome";
		Baidu baidu = newBaidu(); baidu.seleniumTest(); }}Copy the code
  1. Turn picture information into comparable information
public final class PicFinger implements Serializable {
	private static final long serialVersionUID = 431106089062884937L;
	/** * The size of the image fingerprint, resize the image to the specified size to calculate the hash array */
	private static final int HASH_SIZE = 16;
	/** * Save the image fingerprint binarization matrix */
	private final byte[] binaryzationMatrix;

	public PicFinger(byte[] hashValue) {
		if(hashValue.length ! = HASH_SIZE * HASH_SIZE) {throw new IllegalArgumentException(String.format("length of hashValue must be %d", HASH_SIZE * HASH_SIZE));
		}
		this.binaryzationMatrix = hashValue;
	}

	public PicFinger(String hashValue) {
		this(toBytes(hashValue));
	}

	public PicFinger(BufferedImage src) {
		this(hashValue(src));
	}

	public byte[] getBinaryzationMatrix() {
		return binaryzationMatrix;
	}

	private static byte[] hashValue(BufferedImage src) {
		BufferedImage hashImage = resize(src, HASH_SIZE, HASH_SIZE);
		byte[] matrixGray = (byte[]) toGray(hashImage).getData().getDataElements(0.0, HASH_SIZE, HASH_SIZE, null);
		return binaryzation(matrixGray);
	}

	/** * create fingerprint from compressed format {@linkPicFinger} object * *@param compactValue
	 * @return* /
	public static PicFinger createFromCompact(byte[] compactValue) {
		return new PicFinger(uncompact(compactValue));
	}

	public static boolean validHashValue(byte[] hashValue) {
		if(hashValue.length ! = HASH_SIZE) {return false;
		}
		for (byte b : hashValue) {
			{
				if (0! = b &&1! = b) {return false; }}}return true;
	}

	public static boolean validHashValue(String hashValue) {
		if(hashValue.length() ! = HASH_SIZE) {return false;
		}
		for (int i = 0; i < hashValue.length(); ++i) {
			if ('0'! = hashValue.charAt(i) &&'1'! = hashValue.charAt(i)) {return false; }}return true;
	}

	public byte[] compact() {
		return compact(binaryzationMatrix);
	}

	/** * Fingerprint data compression by bit **@param hashValue
	 * @return* /
	private static byte[] compact(byte[] hashValue) {
		byte[] result = new byte[(hashValue.length + 7) > >3];
		byte b = 0;
		for (int i = 0; i < hashValue.length; ++i) {
			if (0 == (i & 7)) {
				b = 0;
			}
			if (1 == hashValue[i]) {
				b |= 1 << (i & 7);
			} else if(hashValue[i] ! =0) {
				throw new IllegalArgumentException("invalid hashValue,every element must be 0 or 1");
			}
			if (7 == (i & 7) || i == hashValue.length - 1) {
				result[i >> 3] = b; }}return result;
	}

	/** * fingerprint decompression in compressed format **@param compactValue
	 * @return* /
	private static byte[] uncompact(byte[] compactValue) {
		byte[] result = new byte[compactValue.length << 3];
		for (int i = 0; i < result.length; ++i) {
			if ((compactValue[i >> 3] & (1 << (i & 7))) = =0) {
				result[i] = 0;
			} else {
				result[i] = 1; }}return result;
	}

	/** * String fingerprint data to byte array **@param hashValue
	 * @return* /
	private static byte[] toBytes(String hashValue) {
		hashValue = hashValue.replaceAll("\\s"."");
		byte[] result = new byte[hashValue.length()];
		for (int i = 0; i < result.length; ++i) {
			char c = hashValue.charAt(i);
			if ('0' == c) {
				result[i] = 0;
			} else if ('1' == c) {
				result[i] = 1;
			} else {
				throw new IllegalArgumentException("invalid hashValue String"); }}return result;
	}

	/** * Scale the image to the specified size **@param src
	 * @param width
	 * @param height
	 * @return* /
	private static BufferedImage resize(Image src, int width, int height) {
		BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
		Graphics g = result.getGraphics();
		try {
			g.drawImage(src.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0.0.null);
		} finally {
			g.dispose();
		}
		return result;
	}

	/** * calculate the mean **@param src
	 * @return* /
	private static int mean(byte[] src) {
		long sum = 0;
		// Convert an array element to an unsigned integer
		for (byte b : src) {
			sum += (long) b & 0xff;
		}
		return (int) (Math.round((float) sum / src.length));
	}

	/** * binary processing **@param src
	 * @return* /
	private static byte[] binaryzation(byte[] src) {
		byte[] dst = src.clone();
		int mean = mean(src);
		for (int i = 0; i < dst.length; ++i) {
			// Convert an array element to an unsigned integer for comparison
			dst[i] = (byte) (((int) dst[i] & 0xff) >= mean ? 1 : 0);
		}
		return dst;

	}

	/** * to grayscale image **@param src
	 * @return* /
	private static BufferedImage toGray(BufferedImage src) {
		if (src.getType() == BufferedImage.TYPE_BYTE_GRAY) {
			return src;
		} else {
			// The image grays
			BufferedImage grayImage = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
			new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null).filter(src, grayImage);
			returngrayImage; }}@Override
	public String toString(a) {
		return toString(true);
	}

	/ * * *@paramMultiLine * Whether to branch *@return* /
	public String toString(boolean multiLine) {
		StringBuffer buffer = new StringBuffer();
		int count = 0;
		for (byte b : this.binaryzationMatrix) {
			buffer.append(0 == b ? '0' : '1');
			if (multiLine && ++count % HASH_SIZE == 0) {
				buffer.append('\n'); }}return buffer.toString();
	}

	@Override
	public boolean equals(Object obj) {
		if (obj instanceof PicFinger) {
			return Arrays.equals(this.binaryzationMatrix, ((PicFinger) obj).binaryzationMatrix);
		} else {
			return super.equals(obj); }}/** * Compares the fingerprint similarity with the specified compression format **@param compactValue
	 * @return
	 * @see #compare(PicFinger)
	 */
	public float compareCompact(byte[] compactValue) {
		return compare(createFromCompact(compactValue));
	}

	/ * * *@param hashValue
	 * @return
	 * @see #compare(PicFinger)
	 */
	public float compare(String hashValue) {
		return compare(new PicFinger(hashValue));
	}

	/** * Compares the similarity with the specified fingerprint **@param hashValue
	 * @return
	 * @see #compare(PicFinger)
	 */
	public float compare(byte[] hashValue) {
		return compare(new PicFinger(hashValue));
	}

	/** * Compare to the specified image **@param image2
	 * @return
	 * @see #compare(PicFinger)
	 */
	public float compare(BufferedImage image2) {
		return compare(new PicFinger(image2));
	}

	/** * Compare fingerprint similarity **@param src
	 * @return
	 * @see #compare(byte[], byte[])
	 */
	public float compare(PicFinger src) {
		if(src.binaryzationMatrix.length ! =this.binaryzationMatrix.length) {
			throw new IllegalArgumentException("length of hashValue is mismatch");
		}
		return compare(binaryzationMatrix, src.binaryzationMatrix);
	}

	/** * Check the similarity of two arrays. The array length must be the same or throw an exception **@param f1
	 * @param f2
	 * @returnReturn similarity (0.0 ~ 1.0) */
	private static float compare(byte[] f1, byte[] f2) {
		if(f1.length ! = f2.length) {throw new IllegalArgumentException("mismatch FingerPrint length");
		}
		int sameCount = 0;
		for (int i = 0; i < f1.length; ++i) {
			{
				if(f1[i] == f2[i]) { ++sameCount; }}}return (float) sameCount / f1.length;
	}

	public static float compareCompact(byte[] f1, byte[] f2) {
		return compare(uncompact(f1), uncompact(f2));
	}

	public static float compare(BufferedImage image1, BufferedImage image2) {
		return new PicFinger(image1).compare(new PicFinger(image2));
	}

	public static Map<String, byte[]> getLibMatrix(List<File> imgListLib) {
		Map<String, byte[]> binMap = new ConcurrentHashMap<String, byte[] > (); BufferedImage libBuf =null;
		PicFinger fpLib = null;
		// Initialize the Lib library
		String fileName = null;
		System.out.print("getLibMatrix() imgListLib size=" + imgListLib.size());
		int c = 0;
		for (File imgfileLib : imgListLib) {
			if (imgfileLib.exists()) {
				fileName = imgfileLib.getName();
				fileName = fileName.substring(0, fileName.indexOf("."));
				try {
					libBuf = ImageIO.read(imgfileLib);
				} catch (IOException e) {
					e.printStackTrace();
				}
				if(libBuf ! =null) {
					fpLib = new PicFinger(libBuf);
					binMap.put(fileName, fpLib.getBinaryzationMatrix());
					if (c % 100= =0) {
						System.out.print("\ngetLib() list c=" + c + "");
					}
					System.out.print(fileName + ",");
					c++;
				} else {
					System.out.println("libBuf=" + libBuf + "|imgfileLib="+ imgfileLib.getName()); }}else {
				continue;
			}
		}
		System.out.println("\ngetLibMatrix() size=" + binMap.size());
		returnbinMap; }}Copy the code
  1. Rotate the image 360°
public static Color bgColor = new Color(255.255.255);

	/** * Create a rotated image at any Angle **@param image
	 * @param theta
	 * @param backgroundColor
	 * @return* /
	public BufferedImage rotateImage(BufferedImage image, double theta, Color backgroundColor) {
		int width = image.getWidth();
		int height = image.getHeight();
		double angle = theta * Math.PI / 180; // Degrees turn radians
		double[] xCoords = getX(width / 2, height / 2, angle);
		double[] yCoords = getY(width / 2, height / 2, angle);
		int WIDTH = (int) (xCoords[3] - xCoords[0]);
		int HEIGHT = (int) (yCoords[3] - yCoords[0]);
		BufferedImage resultImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
		for (int i = 0; i < WIDTH; i++) {
			for (int j = 0; j < HEIGHT; j++) {
				int x = i - WIDTH / 2;
				int y = HEIGHT / 2 - j;
				double radius = Math.sqrt(x * x + y * y);
				double angle1;
				if (y > 0) {
					angle1 = Math.acos(x / radius);
				} else {
					angle1 = 2 * Math.PI - Math.acos(x / radius);
				}
				x = (int) Math.round(radius * Math.cos(angle1 - angle));
				y = (int) Math.round(radius * Math.sin(angle1 - angle));
				if (x < (width / 2) & x > -(width / 2) & y < (height / 2) & y > -(height / 2)) {
					int rgb = image.getRGB((int) Math.round(x + width / 2), (int) Math.round(height / 2 - y));
					resultImage.setRGB(i, j, rgb);
				} else {
					resultImage.setRGB(i, j, -1); }}}return resultImage;
	}

	// Get the Y coordinates of the four corners after rotation
	private double[] getY(int i, int j, double angle) {
		double results[] = new double[4];
		double radius = Math.sqrt(i * i + j * j);
		double angle1 = Math.asin(j / radius);
		results[0] = radius * Math.sin(angle1 + angle);
		results[1] = radius * Math.sin(Math.PI - angle1 + angle);
		results[2] = -results[0];
		results[3] = -results[1];
		Arrays.sort(results);
		return results;
	}

	// Get the X coordinates of the four corners after rotation
	private double[] getX(int i, int j, double angle) {
		double results[] = new double[4];
		double radius = Math.sqrt(i * i + j * j);
		double angle1 = Math.acos(i / radius);
		results[0] = radius * Math.cos(angle1 + angle);
		results[1] = radius * Math.cos(Math.PI - angle1 + angle);
		results[2] = -results[0];
		results[3] = -results[1];
		Arrays.sort(results);
		return results;
	}

	public BufferedImage writeCyclePic(BufferedImage image) {
		BufferedImage newImage = new BufferedImage(152.152, BufferedImage.TYPE_INT_BGR);
		try {
			int width = image.getWidth();
			int heigth = image.getHeight();
			double x0 = width / 2;
			double y0 = heigth / 2;
			int woffset = (width - 152) / 2;
			int hoffset = (heigth - 152) / 2;
			for (int i = woffset; i < 152 + woffset; i++) {
				for (int j = hoffset; j < 152 + hoffset; j++) {
					double r = Math.sqrt(Math.pow(Math.abs(i - x0), 2.0) + Math.pow(Math.abs(j - y0), 2.0));
					if (r > (x0 - woffset)) {
						newImage.setRGB(i - woffset, j - hoffset, -1);
					} else{ newImage.setRGB(i - woffset, j - hoffset, image.getRGB(i, j)); }}}return newImage;
		} catch (Exception e) {
			e.printStackTrace();
			return null; }}// Rotate to generate the image
	//start The distance needed to slide the original image to normal
	//total Maximum distance
	//input original distance
	//outPath new map directory
	public void rotate360(Integer start, Integer total, File input, String outPath) {
		try {
			BufferedImage image = ImageIO.read(input);
			int distance;
			BufferedImage mid, result;
			File output;
			for (int i = 0; i < 360; i++) {
				distance = start + Math.round(i * total / 360);
				distance = distance > total ? distance - total : distance;
				mid = rotateImage(image, i, bgColor);
				result = writeCyclePic(mid);
				if(outPath ! =null&&!"".equals(outPath)) {
					output = new File(outPath+i+"-"+distance+".png");
					ImageIO.write(result, "png", output); }}}catch(Exception e) { e.printStackTrace(); }}Copy the code
  1. The picture model is converted into a comparable object and stored in the model library
//Map
      
       >
      ,>
// The second String records the distance to slide, PicFinger is the comparison of picture information
public static Map<String, Map<String, PicFinger>> allMap = new HashMap<String, Map<String, PicFinger>>();

	public static PicFinger getPicFinger(File file) {
		byte[] img;
		try {
			BufferedImage libBuf = ImageIO.read(file);
			PicFinger picFinger = new PicFinger(libBuf);
			img = picFinger.getBinaryzationMatrix();
			PicFinger fp = new PicFinger(img);
			return fp;
		} catch (IOException e) {
			e.printStackTrace();
			return null; }}public static List<File> getFiles(String path) {
		File root = new File(path);
		List<File> files = new ArrayList<File>();
		if(! root.isDirectory()) { files.add(root); }else {
			File[] subFiles = root.listFiles();
			for(File f : subFiles) { files.addAll(getFiles(f.getAbsolutePath())); }}return files;
	}
	
	public static void save(String file, Object o) throws Exception {
		FileOutputStream outStream = null;
		ObjectOutputStream objectOutputStream = null;
		try {
			outStream = new FileOutputStream(file);
			objectOutputStream = new ObjectOutputStream(outStream);
			objectOutputStream.writeObject(o);
			objectOutputStream.close();
		} catch (Exception e) {
		} finally {
			if(outStream ! =null)
				outStream.close();
			if(objectOutputStream ! =null) objectOutputStream.close(); }}public static Object load(String file) throws Exception {
		FileInputStream freader = null;
		ObjectInputStream objectInputStream = null;
		try {
			freader = new FileInputStream(file);
			objectInputStream = new ObjectInputStream(freader);
			Object o = objectInputStream.readObject();
			return o;
		} catch (Exception e) {
			return null;
		} finally {
			if(freader ! =null)
				freader.close();
			if(objectInputStream ! =null) objectInputStream.close(); }}Copy the code

4. Results presentation

With all the procedures gone, take a test.

On a cursory inspection, the results are good. Inevitably, there are also identification errors, and the next result analysis.

5. Result analysis

Goal:

Identify the picture Angle, calculate the corresponding sliding distance, simulate sliding.

Implementation idea:

Images are captured, image models from various angles are screened and generated, and forward images are marked to calculate the distance and integrate model data. Model library is built. After images are captured, the model library is matched by image similarity comparison algorithm according to the matched distance to simulate sliding

Detection time:

15-100 milliseconds

Pass:

95% (low sample)

The final test result is 300 samples, which is still too small. It is not sure whether such effect will be achieved in more tests. It should not be too far.

Six, the concluding

This is the end of this article, thank you for stopping to watch, you click a follow, click a like ~

Thank you, big guy


Author: Sweet taro taste cat,