I think what you're looking for is local adaptive thresholding (via the magick::image_lat() function). Below is some code I used to process a few hundred pages that produced reasonable results. Note that I also used image_deskew()...tesseract is (I think) fairly sensitive to having straight lines be straight. The cropping is probably specific to my images, but the resolution of the images did seem to matter as I remember (this was a while ago, and results are probably better using the new version of tesseract).
library(magick)
img_files <- list.files(pattern = "[0-9]\\.png$", full.names = TRUE)
message("Cleaning image files...")
for(img_file in img_files) {
message(img_file)
img <- image_read(img_file) %>%
image_crop(geometry_area(width = 1500, height = 2100, x_off = 150, y_off = 50)) %>%
image_convert(colorspace = "gray") %>%
image_negate() %>%
# local adaptive thresholding
image_lat(geometry = "20x10+5%") %>%
image_negate() %>%
image_deskew() %>%
image_trim() %>%
image_threshold() %>%
image_border(geometry = "50x50", color = "white")
image_write(img, str_replace(img_file, ".png$", ".clean.png"))
}