You are given an image representing a scanned OMR answer sheet. Each image contains a grid of circles, with each row representing one question and each column representing a possible answer (A, B, C, D). Some circles are filled to indicate the selected answer by the candidate.

Your task is to write a program that takes the image as input, along with an array containing the correct answers for each question and returns a score based on the number of correct answers. For each correct answer, score will be incremented by 1 point. Each question has only 1 correct answer.

The filled circles in the images can be either fully filled (360 degrees filled) or partially filled. A fully filled circle represents a definite answer, while a partially filled circle represents a probable answer. If a circle is filled more than 75% (270 degrees filled) of the area, it should be considered as a definite answer.
Sample OMR images

For the below image, when evaluating with the expected answer as D A D C, the score is evaluated as 4

image

For the below image, where partial circles are filled, when evaluating with expected answer as C D D D, the score is evaluated as 3

image

Note

Few things to keep in mind while evaluating the score

A filled circle is considered definite answer when 75% of the circle area is filled, which means 270 degress or more must be filled to consider it as a definite answer.

If a candidate has marked more than one circle as definite answer for a question, then even if the definite answers contains the correct answer, no score will be provided for that question.

Input Format
Guidelines

First line in the standard input represents the image to be used eg. omr_sheet_1.png
Second line in the standard input represents the correct answer for the omr sheet, separated by a space

Sample Input

omr_sheet_1.png
D A D C
Reading the Input

You can read the input as standard input.

To load the image, you can load it as following:
Python

//read from standard input filename = input() // get file if os.path.isfile(filename):
Open the file

with open(filename, 'r') as file:
...
Java

import java.io.File;
...
// read from standard input Scanner scanner = new Scanner(System.in); String query = scanner.nextLine(); // Get the image file
File file = new File("omr_sheet_1.png");

Constraints
Image constraints

All Image dimensions are 500 x 500
2 color present only, black & white.
Every image has 4 Questions with 4 options.
Every Question has only 1 correct question.

Output Format
Guidelines

Please output only the score in standard output

you can use only these libraries
requests[security]@2.22.0, beautifulsoup4@4.8.1, pycrypto@2.6.1, cryptography@2.8, python-dateutil@2.8.1, urllib3@1.25.7, pyyaml@5.2, numpy@1.16.5, scipy@1.2.2, sympy@1.4, scikit-learn@0.20.4, nltk@3.4.5, pandas@0.24.2, statsmodels@0.10.2

i am getting runtime error in my code for a particular case
import struct
import zlib

def get_png_pixel_data(filename):
    # Read the PNG file
    with open(filename, 'rb') as f:
        # Check PNG signature
        signature = f.read(8)
        if signature != b'\x89PNG\r\n\x1a\n':
            raise ValueError("Not a valid PNG file")

        width = height = None
        image_data = b''
        color_type = None
        bit_depth = None

        # Read chunks until we find IHDR (image header) and IDAT (image data)
        while True:
            # Read chunk length and type
            chunk_len, chunk_type = struct.unpack(">I4s", f.read(8))
            chunk_data = f.read(chunk_len)
            f.read(4)  # CRC, not used here

            if chunk_type == b'IHDR':  # Header chunk
                width, height, bit_depth, color_type, compression, filter_method, interlace = struct.unpack(">IIBBBBB", chunk_data)
                # print(f"Image size: {width}x{height}, bit depth: {bit_depth}, color type: {color_type}")
                if width != 500 or height != 500:
                    raise ValueError("Only 500x500 images are supported")
            elif chunk_type == b'IDAT':  # Image data chunk
                image_data += chunk_data
            elif chunk_type == b'IEND':  # End of PNG file
                break

        # Decompress the image data
        decompressed_data = zlib.decompress(image_data)

        # For grayscale conversion: 
        # color_type 2 means RGB, we need to convert it to grayscale
        grayscale_image = [[0 for _ in range(width)] for _ in range(height)]  # Create a 500x500 array
        
        if color_type == 2:  # RGB image
            row_size = width * 3  # 3 bytes per pixel (RGB)
            for y in range(height):
                filter_type = decompressed_data[y * (row_size + 1)]  # Ignore filter type for now
                row_data = decompressed_data[y * (row_size + 1) + 1: (y + 1) * (row_size + 1)]
                for x in range(0, row_size, 3):  # Read RGB triplet
                    r = row_data[x]
                    g = row_data[x + 1]
                    b = row_data[x + 2]
                    # Convert to grayscale using the luminosity formula
                    grayscale_value = int(0.299 * r + 0.587 * g + 0.114 * b)
                    grayscale_image[y][x // 3] = grayscale_value

        elif color_type == 0:  # Already grayscale
            row_size = width  # 1 byte per pixel in grayscale
            for y in range(height):
                filter_type = decompressed_data[y * (row_size + 1)]  # Ignore filter type for now
                row_data = decompressed_data[y * (row_size + 1) + 1: (y + 1) * (row_size + 1)]
                for x in range(width):
                    grayscale_image[y][x] = row_data[x]

        else:
            raise ValueError("Unsupported PNG color type")

        return grayscale_image

# Example usage
filename = input()

char_to_num = {
    'A': 0,
    'B': 1,
    'C': 2,
    'D': 3
}

# Convert the string to an array of numbers
num_array = [char_to_num[char] for char in input().split()]


grayscale_image = get_png_pixel_data(filename)


# Assuming a 500x500 grayscale image
image_height = len(grayscale_image)
image_width = len(grayscale_image[0])

# print(image_height,image_width)
window_size = 32

col_start_pts = [32,162,296,432]
row_start_pts = [36,168,300,432]

correct_ans = 0
answered_qs = set()

# Loop through the image in 32x32 blocks
for idx,row_start in enumerate(row_start_pts):
    for idy,col_start in enumerate(col_start_pts):
        black_pixel_count = 0
        total_pixels = window_size * window_size
        
        # Traverse through the 32x32 block
        for row in range(row_start, min(row_start + window_size, image_height)):
            for col in range(col_start, min(col_start + window_size, image_width)):
                # Check if the pixel is black (assuming black is value 0)
                if grayscale_image[row][col] == 0:
                    black_pixel_count += 1

        # Calculate the percentage of black pixels in the current 32x32 block
        black_percentage = (black_pixel_count / total_pixels) * 100
        if black_percentage>50:
            if idx in answered_qs:
                correct_ans-=1
                answered_qs.remove(idx)
            elif num_array[idx] == idy:
                correct_ans+=1
                answered_qs.add(idx)
        
        # print(f"Block ({col_start}, {row_start}) - Black Pixel %: {black_percentage:.2f}%")
        
print(correct_ans)

fix it