paint-brush
How to Create a Simple Object Detector with NextJsby@guesthu
695 reads
695 reads

How to Create a Simple Object Detector with NextJs

by Guest Hu
Guest Hu HackerNoon profile picture

Guest Hu

@guesthu

A web developer who loves writing and painting.

November 6th, 2021
Read on Terminal Reader
Read this story in a terminal
Print this story
Read this story w/o Javascript
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

The function of this simple app is to indicate the object’s location in the image whenever the user clicks any of the labeled buttons. It shows the object's location in an image whenever a user clicks a button. The app was created with NextJs.
featured image - How to Create a Simple Object Detector with NextJs
1x
Read by Dr. One voice-avatar

Listen to this story

Guest Hu HackerNoon profile picture
Guest Hu

Guest Hu

@guesthu

A web developer who loves writing and painting.

About @guesthu
LEARN MORE ABOUT @GUESTHU'S
EXPERTISE AND PLACE ON THE INTERNET.

The function of this simple app is to indicate the object’s location in the image whenever the user clicks any of the labeled buttons.


To begin with, first, I created a simple design layout. (Bootstrap 5 was installed).

const ImageDetector = () =>{
 return(
    <>
        <div className="row container">
            <p className="text-center"><strong>SIMPLE IMAGE LABELING</strong></p>
            <div className="row mt-2 mb-3">
                <div className="col-4">
                    {/*buttons here*/}
                </div>
                <div className="col-8">
                    <img
                    id="image" 
                    src={`/img/foods.jpg`} 
                    alt="photo"
                    className="w-100"
                    />
                </div>
            </div>
        </div>
    </>
 )
}
export default ImageDetector;


I declared a variable containing an array of objects.

const objects = [
        {
            "object": "juice",
            "x":1,
            "y":1,
            "w":230,
            "h":250
        },
        {
            "object": "oranges",
            "x":200,
            "y":230,
            "w":320,
            "h":230
        },
        {
            "object": "bread",
            "x":600,
            "y":280,
            "w":250,
            "h":250
        },
    ];


After declaration, I fetched the values from that variable, objects, and converted them into buttons.

                <div className="col-4">
                    {objects.map(item=>(
                        <button 
                        className={"btn btn-secondary col-12 my-2"} 
                        key={item.object}
                        >
                        {item.object}
                        </button>
                    ))}
                </div>


To display the square or rectangle shape, I declared width and height variables to get the natural width and height of the image.

const [width, setWidth] = useState(0);
const [height, setHeight] = useState(0);

useEffect(()=>{  
    const image = document.querySelector<HTMLImageElement>('#image');
    if(image !== null){
        let linkSource = image.src;
        const imageCopy = document.createElement("img");
        imageCopy.src = linkSource;
        setWidth(imageCopy.width);
        setHeight(imageCopy.height);
    }
},[]);

Then, I inserted <svg/> below the <img/> and put them inside a <div/> then made its position relative. I defined the css style of the <svg/> to overlay the <img/>. The preserveAspectRatio and viewBox in <svg/> will help retain the x and y positions of rect and text elements even when the screen size changes.

<div className="col-8">
    <div style={{"position":"relative"}}>
        <img
        id="image" 
        src={`/img/foods.jpg`} 
        alt="photo"
        className="w-100"
        />
        <svg 
        preserveAspectRatio="none" 
        className="image-map"
        viewBox={`0,0,${width},${height}`}
        <rect className="selected-object" rect>
        <rect className="wrap-text" ></rect>
        <text className="object-name"> </text>
        </svg>
    </div>
</div>

<style jsx>
    {`
        .image-map {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            -webkit-user-select: none;
            -moz-user-select: none;
            -ms-user-select: none;
            -o-user-select: none;
            user-select: none;
        }
        .selected-object{
            position: absolute;
            top: 0;
            left: 0;
        }
    `}
</style>

I inserted variables to set values of the x,y,w,h in svg’s rect and text elements.

const [xPosition, setXPosition] = useState(0);
const [yPosition, setYPosition] = useState(0);
const [objWidth, setObjWidth] = useState(0);
const [objHeight, setObjHeight] = useState(0);
const [selectedItem, setSelectedItem] = useState("");


Created handleClick() so when the user clicks a button the rect svg will appear.

const handleClick = ( object:string ) =>{
    objects.map(item =>{
        if(item.object === object){
            setXPosition(item.x);
            setYPosition(item.y);
            setObjWidth(item.w);
            setObjHeight(item.h);
            setSelectedItem(object.toUpperCase());
        }
    });
}
<div className="col-4">
    {objects.map(item=>(
        <button 
        className={"btn btn-secondary col-12 my-2"} 
        key={item.object}
        onClick={() => handleClick(item.object)} 
        >
        {item.object}
        </button>
    ))}
</div>


Then I set the values of rect and text elements and edited my style css.

<rect className="selected-object" 
x={xPosition} 
y={yPosition}
width={objWidth} 
height={objHeight}></rect>
<rect className="wrap-text" 
x={xPosition} 
y={yPosition} 
width={objWidth} 
height="20"></rect>
<text className="object-name" 
x={xPosition} 
y={yPosition+15}>{selectedItem}</text>


<style jsx>
    {`
        .image-map {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            -webkit-user-select: none;
            -moz-user-select: none;
            -ms-user-select: none;
            -o-user-select: none;
            user-select: none;
        }
        
        .selected-object{
            position: absolute;
            top: 0;
            left: 0;
            fill: transparent;
            stroke: #ff9e0d;
            stroke-width: 5px;
        }
        .wrap-text{
            fill: #ff9e0d;
        }
        .object-name{
            z-index:999;
        }
    `}
</style>


And it’s done. You can now run your simple app.

L O A D I N G
. . . comments & more!

About Author

Guest Hu HackerNoon profile picture
Guest Hu@guesthu
A web developer who loves writing and painting.

TOPICS

THIS ARTICLE WAS FEATURED IN...

Permanent on Arweave
Read on Terminal Reader
Read this story in a terminal
 Terminal
Read this story w/o Javascript
Read this story w/o Javascript
 Lite
Hashnode
Learnrepo
X REMOVE AD