How can i keep only the page number from a scanned book page

i used this

import sys
import cv2
from matplotlib import pyplot as plt

def GetBoundingRectangles(IMG_PATH, output_path):
img = cv2.imread(IMG_PATH)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray2 = gray.copy()
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
contours, hier = cv2.findContours(thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

secs = []
for cnt in contours:
    if 550 < cv2.contourArea(cnt) < 1050:
        (x, y, w, h) = cv2.boundingRect(cnt)
        cv2.rectangle(gray2, (x, y), (x+w, y+h), 0)
        secs.append(gray2[y:y+h, x:x+w])


cv2.imwrite(output_path, gray2)

image_path = 'a.jpg'
output_path = 'processed_image.jpg'
GetBoundingRectangles(image_path, output_path)

on that


the result is like this

1 do u know how can i keep only the page number area ?
the page number usually is top left , top right , bottom left , bottom right or in the middle down

2 do u know how can i white everything outside the black boxes inside the image and keep anything inside ?

i know that it is not the most proper way but that is what i wanted


to this

and finally

import sys
import cv2
import numpy as np

def apply_otsu_threshold(input_path, output_path):
    # Load the image in grayscale
    image = cv2.imread(input_path, cv2.IMREAD_GRAYSCALE)

    # Apply Otsu's thresholding
    _, thresholded_image = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

    # Save the result
    cv2.imwrite(output_path, thresholded_image)

# Example usage
input_image_path = 'a.jpg'
output_image_path = 'temp.jpg'
apply_otsu_threshold(input_image_path, output_image_path)

def GetBoundingCircles(IMG_PATH, min_black_pixels, max_black_pixels, min_white_pixels, max_white_pixels):
    img = cv2.imread(IMG_PATH)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # Apply Otsu's thresholding
    ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

    # Find contours
    contours, hier = cv2.findContours(thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

    total_black_pixels = 0
    total_white_pixels = 0
    total_circles = 0

    for circle_number, cnt in enumerate(contours, 1):
        if 200 < cv2.contourArea(cnt) < 1000:
            (x, y), radius = cv2.minEnclosingCircle(cnt)
            center = (int(x), int(y))

            # Only draw the first circle with radius * 3.4
            radius1 = int(radius * 3.4)
            cv2.circle(gray, center, radius1, 0, 2)

            # Get the region of interest (ROI) inside the circle
            roi = gray[int(y - radius1):int(y + radius1), int(x - radius1):int(x + radius1)]

            # Count the number of black and white pixels in the ROI
            black_pixels = np.sum(roi == 0)
            white_pixels = np.sum(roi == 255)

            total_black_pixels += black_pixels
            total_white_pixels += white_pixels
            total_circles += 1

            # Check if the number of black pixels is within the specified range
            # and the number of white pixels is within the specified range
            if not min_black_pixels <= black_pixels <= max_black_pixels or not min_white_pixels <= white_pixels <= max_white_pixels:
                # If the conditions are met, make everything inside the drawn circle white
                gray[int(y - radius1):int(y + radius1), int(x - radius1):int(x + radius1)] = 255

    # Calculate the average number of black and white pixels for circles
    average_black_pixels = total_black_pixels / total_circles
    average_white_pixels = total_white_pixels / total_circles

    # Print the total and average numbers
    #print(f"Total Black Pixels in Circles: {total_black_pixels}")
    #print(f"Total White Pixels in Circles: {total_white_pixels}")
    #print(f"Average Black Pixels per Circle: {average_black_pixels}")
    #print(f"Average White Pixels per Circle: {average_white_pixels}")
    #print(f"Total Circles: {total_circles}")

    cv2.imwrite('result.jpg', gray)

image_path = 'temp.jpg'
min_black_pixels = 2500  # Adjust this value based on your requirements
max_black_pixels = 2600  # Adjust this value based on your requirements
min_white_pixels = 26000  # Adjust this value based on your requirements
max_white_pixels = 30000  # Adjust this value based on your requirements

GetBoundingCircles(image_path, min_black_pixels, max_black_pixels, min_white_pixels, max_white_pixels)

ok i need to find out how to crop only the circle or make white the backround but is is still good

i used the code to that

result


# Import the libraries
 import cv2
 import numpy as np
 from PIL import Image
 
 # Read the image
 img = cv2.imread("a.jpg")
 
 # Convert to grayscale
 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
 
 # Threshold the image to keep only the black pixels
 thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
 
 # Find the contours of the black regions
 contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]
 
 # Sort the contours by area in descending order
 contours = sorted(contours, key=cv2.contourArea, reverse=True)
 
 # Loop through the contours
 for c in contours:
     # Get the bounding rectangle of the contour
     x, y, w, h = cv2.boundingRect(c)
     
     # Check if the contour is at the bottom right corner of the image
     if x + w > img.shape[1] * 0.9 and y + h > img.shape[0] * 0.9:
         # Increase the radius for a larger circular mask
         radius = int(max(w, h) * 3.5)  # Adjust the factor as needed
         
         # Create a circular mask using the contour information and larger radius
         mask = np.zeros_like(gray)
         cv2.circle(mask, (x + w // 2, y + h // 2), radius, (255), thickness=cv2.FILLED)
         
         # Apply the circular mask to the original image to keep only what's inside the circle
         result = cv2.bitwise_and(img, img, mask=mask)
         
         # Resize the result to a higher resolution
         result = cv2.resize(result, (img.shape[1] * 1, img.shape[0] * 1), interpolation=cv2.INTER_CUBIC)
         
         # Save the cropped circular region in better resolution using Pillow
         output_path = "cropped_large_circle_high_resolution.jpg"
         result_pil = Image.fromarray(cv2.cvtColor(result, cv2.COLOR_BGR2RGB))
         result_pil.save(output_path, dpi=(600, 600))
         
         # Break the loop
         break

ok i figure out what i wanted i think i find how to detect page number from a page

this is the black n white page on the top right is the pattern i want to crop ,this match with page number from multiple even pages ,the one i uploaded input.jpg is an example image [img] [https://i.stack.imgur.com/llYiq.png] [img]

output.txt
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
0000#0#######################0#####################00##00000
000##0##############################################0##00000
000#################################################00000000
000#################################################00000000
000#################################################00000000
000#################################################00000000
000#################################################00000000
000#################################################00000000
000##################################################0000000
000##################################################0000000
000##################################################0000000
000##################################################0000000
000##################################################0000000
000##################################################0000000
000##################################################0000000
000##################################################0000000
000##################################################0000000
000##################################################0000000
000##################################################0000000
000####################################################00000
000####################################################00000
000####################################################00000
000####################################################00000
000####################################################00000
000####################################################00000
000####################################################00000
000###0#######################0########################00000
000###0#######################0########################00000
000###0#######################0########################00000
000###0#######################0#####################0##00000
000###0#######################0#####################0##00000
000###0#######################0#####################0##00000
000###0#######################00########0###########0##00000
000000000000000000000000000000000000000000000000000000000000
####0000000000000000000000000000#00####00#0###000#00########
############################################################
00#0##0##0###000000000#0##000000#########00000##0000000#0000
00#0#0#0#0#000#00#000#00##00000##########000#00##0##00#00000
0###0#00###0##00#000####000#0#00###################00#000000
0#00##00####0#000000##00###0000#######0########0######000000

this is the pattern i will try to crop here is on top left

0000
0##0
0##0
0000
0000

this is the code


import cv2
import numpy as np

# Load the cropped image in grayscale
image = cv2.imread('input.jpg', cv2.IMREAD_GRAYSCALE)

# Get the height and width of the image
h, w = image.shape

# Define the number of rows and columns of the grid
rows = 45
cols = 60

# Calculate the size of each square in pixels
square_h = h // rows
square_w = w // cols

# Create an empty array to store the grid values
grid = np.empty((rows, cols), dtype=str)

# Loop over the rows and columns of the grid
for i in range(rows):
    for j in range(cols):
        # Get the coordinates of the top left corner of the square
        x = j * square_w
        y = i * square_h

        # Get the sub-image corresponding to the square
        square = image[y:y+square_h, x:x+square_w]

        # Check if the square contains any black pixel
        if np.any(square < 255):
            # Set the grid value to '#'
            grid[i, j] = '#'
        else:
            # Set the grid value to '0'
            grid[i, j] = '0'

# Write the result to output.txt
with open('output.txt', 'w') as file:
    for i in range(rows):
        for j in range(cols):
            file.write(grid[i, j])
        file.write('\n')

# Pattern matching
pattern = [
    '0000',
    '0##0',
    '0##0',
    '0000',
    '0000'
]

with open("output.txt", "r") as file:
    content = file.read()

lines = content.split('\n')

for i in range(len(lines) - len(pattern) + 1):
    for j in range(len(lines[i]) - len(pattern[0]) + 1):
        match = True
        for k in range(len(pattern)):
            if lines[i + k][j:j+len(pattern[0])] != pattern[k]:
                match = False
                break
        if match:
            print(f"Pattern found at line {i+1}, position {j+1}")

            # Crop the region where the pattern is found
            x_start = j * square_w
            y_start = i * square_h
            x_end = (j + len(pattern[0])) * square_w
            y_end = (i + len(pattern)) * square_h

            cropped_image = image[y_start:y_end, x_start:x_end]

            # Save the cropped image
            cv2.imwrite('cropped_page_number.jpg', cropped_image)

	

[img] [1]: https://i.stack.imgur.com/jMjSB.jpg [img]