OpenCV: lossless capture?

Viewed 326

I wrote a simple python program that uses OpenCV and scantailor-cli to scan documents with my document camera and store them as high-contrast, low filesize PDFs.

Approach:

  1. capture the document in full color with OpenCV at 1920x1080 in JPG format
  2. convert to high-contrast black-and-white PDF with scantailor-cli

This generally works, however I have discovered an issue with my usage of OpenCV that is limiting the quality of my scans. I'm hoping someone here can give me the nudge I need to improve this.

When I use the UI-based capture software that came with my IPEVO document camera (Visualizer), I get a nice, clearn capture that makes a great conversion into high-contrast. When I use OpenCV, I get unwanted compression artifacts and conversion to high-contrast yields unsatisfactory results.

Comparison of image capture quality between IPEVO Visualizer and OpenCV.  You should be able to see more compression artifacts in the OpenCV image.

Full program listing is here: https://github.com/jonashw/Document-Scanner/blob/master/scan.py

Relevant excerpt below

def do_camera(device_id):
    cam = cv2.VideoCapture(device_id)#,cv2.CAP_DSHOW)
    w,h = 1920,1080
    cam.set(cv2.CAP_PROP_FRAME_WIDTH, w)
    cam.set(cv2.CAP_PROP_FRAME_HEIGHT, h)
    cam.set(cv2.CAP_PROP_FORMAT, 0)
    w = cam.get(cv2.CAP_PROP_FRAME_WIDTH)
    h = cam.get(cv2.CAP_PROP_FRAME_HEIGHT)
    grab_mode = cam.get(cv2.CAP_PROP_MODE)
    format = cam.get(cv2.CAP_PROP_FORMAT)
    print("capturing with w={}, h={}, grab_mode={}, format={}".format(w,h,grab_mode, format))
    
    #ok = False
    #i = -100
    #while (not ok) and i < 10:
        #if i != 0:
            #print("setting grab_mode {}".format(grab_mode + i))
            #ok = cam.set(cv2.CAP_PROP_MODE, grab_mode + i)
        #i += 1
    #if ok:
        #gm = cam.get(cv2.CAP_PROP_MODE)
        #printf("Grab mode = {}", format(gm))

    cv2.namedWindow("test", cv2.WINDOW_NORMAL)

    img_counter = 0
    img_paths = []

    while True:
        ret, frame = cam.read()
        if not ret:
            print("failed to grab frame")
            break
        cv2.imshow("test", frame)
        cv2.resizeWindow("test",1280,720)
        cv2.moveWindow("test",1920,0)

        k = cv2.waitKey(1)
        if k%256 == 27:
            # ESC pressed
            print("Escape hit, closing...")
            break
        elif k%256 == 32:
            # SPACE pressed
            img_name = "capture_{}.png".format(img_counter)
            img_path = os.path.join(capture_path, img_name)
            img_paths.append(img_path)
            os.makedirs(capture_path, exist_ok=True)
            cv2.imwrite(img_path, frame, [cv2.IMWRITE_PNG_COMPRESSION, 0])
            print("{} written!".format(img_name))
            img_counter += 1

    cam.release()

    cv2.destroyAllWindows()
    return img_paths

I suspect the exact line I need to alter is this one.

            cv2.imwrite(img_path, frame, [cv2.IMWRITE_PNG_COMPRESSION, 0])

As you can see, I have opted for PNG format, which should not result in any JPEG-like compression artifacts. Despite this selection, I get artifacts.

I have also tried embracing JPEG and setting the quality to max. This does not improve matters:

        cv2.imwrite(img_path, frame, [cv2.IMWRITE_JPEG_QUALITY, 100])

What can I do? Please and thank you

0 Answers
Related