Aneesh Kotnana
Aneesh Kotnana

Reputation: 61

How to translate a small section of an image using OpenCV in Python

I have the coordinates of the upper left corner of the bottom semicircle and I know how the length and width of the semicircle if it were to be enclosed in a rectangle. What I want to be able to do, is to translate the bottom semicircle up 4 pixels. So could somebody give some code to translate a section of an image knowing all the coordinates? Thanks.

Image

Upvotes: 1

Views: 748

Answers (2)

Aneesh Kotnana
Aneesh Kotnana

Reputation: 61

Thanks for the help @Rachel L, but I figured it out a while ago. Basically I created a separate image containing the semicircle on the bottom, and I used a method to get the top left corner of every semicircle on the bottom. Then I figured out the length and width of the semicircle and just moved all the black pixels in the box that I created up 5 units which aligned it.

I probably should have added that this was part of a bigger project where I needed to move all the semicircles on the bottom from this image so that they were all aligned meaning that I wouldn't know the coordinates of them.image

method for extracting locations of semicircles

def extract(name1, name2):
img_rgb = cv2.imread(name1)
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread(name2,0)   
res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
threshold = 0.8
loc = np.where( res >= threshold)
arr = []
for pt in zip(*loc[::-1]):
    if "down" in name2:
        pt = (pt[0], pt[1] + 1)
    arr.append(pt)
return arr

code to move semicircle up

locFillSemiDown = extract('img' + str(num) + '.png', 'filledsemidown.png')

for loc in locSemiDown:
   for y in range(loc[0], loc[0] + 11):
      for x in range(loc[1], loc[1] + 6):
         if(img.item(x,y,0) == 0 and img.item(x,y,1) == 0 and img.item(x,y,2) == 0):  
            img.itemset((x - 5, y,0),0)
            img.itemset((x - 5, y,1),0)
            img.itemset((x - 5, y,2),0)
            img.itemset((x, y,0),0)
            img.itemset((x, y,1),255)
            img.itemset((x, y,2),255)

enter image description here

Upvotes: 1

Rachel L
Rachel L

Reputation: 327

For that particular image, you can get away with grabbing the rectangle plus 4-6 pixel rows, then put that ROI on the image the 4 pixels higher that you want.

This is in C++, but it should be similar enough you can translate it.

#include "stdafx.h"
#include <opencv/cxcore.h>
#include <opencv2\core\mat.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <opencv/cxcore.h>
#include <opencv/cv.h>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>

using namespace cv;
using namespace std;


int main() {

    //getting the image
    Mat image = imread("C:/this/is/a/link/to/an/image.png");

    //create new image that looks exactly like old image
    Mat new_image = image.clone();

    //showing the image
    namedWindow("Image", CV_WINDOW_NORMAL| CV_WINDOW_KEEPRATIO | CV_GUI_EXPANDED); 
    imshow("Image", image);
    waitKey(0);

    //getting the roi coordinates
    int x = 13, y = 8; //eyeballing the coordinates
    int w = 26-x, h = 20-y; //more eyeballing the coordinates

    //grabbing the roi
    Rect roi = Rect(x, y, w, h);
    Mat img_roi = image(roi);

    //creating the new roi
    Rect new_roi = Rect(x, y-4, w, h);

    //copying the old roi onto the  new image in the space of the new roi
    img_roi.copyTo(new_image(new_roi));

    //displaying the image
    imshow("Image", new_image);
    waitKey(0);

    //saving the new image
    imwrite("C:/this/is/a/link/to/a/newimage.png", new_image);

}

Results in this:

Image of fixed file

Now, this works because you've got more yellow that you can grab below the rectangle you're looking for.

If you trim it to exactly the rectangle you want to move, then it just overlays the roi on the old image, and you'll end up with part of your "moved" image where it was.

Like this:

Image of fixed file with shorter rect

Upvotes: 0

Related Questions